JQuery Easyui Datagrid virtualscrollview View Simple analysis

Source: Internet
Author: User
Tags javascript array

We all know that the advantage of Easyui's DataGrid component when loading large amounts of data is not obvious, compared to some other frameworks, if the amount of data reaches thousands of, it will be slower, especially under IE. In this case, the first thing we do is to optimize the various aspects of the DataGrid component performance, but anything can be solved, Virtualscrollview is a good solution.

Virtualscrollview's guideline is to draw less TR into table, the height of the table is limited, and the user's visible area is very limited, so the amount of data is very large, it is not necessary to draw all the data data into the table, resulting in a large dom, resulting in slower loading speed.

Source Analysis > Source Analysis

The DataGrid component of JQuery Easyui has also expanded a virtualscrollview view, and let's analyze its source code:

  1. var ScrollView = $.extend ({}, $.fn.datagrid.defaults.view, {render:function (target, container, frozen) {
  2. var state = $.data (target, ' DataGrid '); var opts = state.options;
  3. This place should pay special attention, not using the State.data.rows data//instead of the view.rows, and View.rows in the Onbeforerender event is set to undefined
  4. Onbeforerender event in ScrollView, even if the URL method will only be triggered once, so at the first rend, there is no data directly return. var rows = This.rows | | [];
  5. if (!rows.length) {return;
  6. } var fields = $ (target). DataGrid (' Getcolumnfields ', frozen);
  7. If it is rend frozen part, but there is no line number and frozencolumns, then return directly
  8. if (frozen) {if (!) ( Opts.rownumbers | | (Opts.frozencolumns && opts.frozenColumns.length))) {
  9. Return }
  10. }
  11. var index = This.index; var table = ["];
  12. for (var i=0; i<rows.length; i++) = "" "{=" "var=" "css=" opts.rowstyler "? =" "Opts.rowstyler.call (target,=" "index,=" " Rows[i]) = "": = "" "; =" "<li=" "class=" alt "> var classvalue ="; var stylevalue = ';
  13. if (typeof css = = ' string ') {stylevalue = CSS;
  14. } else if (CSS) {classvalue = Css[' class '] | | ‘‘;
  15. Stylevalue = css[' Style ' | | ‘‘; }
  16. var cls = ' class= ' datagrid-row ' + (index% 2 && opts.striped?) ' Datagrid-row-alt ': ') + Classvalue + ' "; var style = Stylevalue? ' style= ' + stylevalue + ' "': ';
  17. Get the class and style attributes for this row//var cls = (index% 2 && opts.striped)? ' class= ' Datagrid-row datagrid-row-alt ': ' class= ' datagrid-row ';
  18. var stylevalue = Opts.rowstyler? Opts.rowStyler.call (target, index, rows[i]): "; var style = Stylevalue? ' style= ' + stylevalue + ' "': ';
  19. var rowId = state.rowidprefix + '-' + (frozen?1:2) + '-' + index; Table.push ('
  20. ‘);
  21. Table.push (This.renderRow.call (this, target, fields, frozen, index, rows[i])); Table.push ('
  22. ‘);
  23. index++; }
  24. Table.push ('
  25. ‘);
  26. $ (container). HTML (Table.join (")); },
  27. /**
  28. * Onbeforerender event, first of all to understand two points: * 1-call loaddata method to load data data, LoadData internal rend before the event is triggered
  29. * 2-url mode, after acquiring the remote data, also uses the LoadData method to load the data, so the URL method will also trigger the Onbeforerender event * @param {dom} target DataGrid Instance host DOM Object
  30. * @return {[type]} [description] */
  31. Onbeforerender:function (target) {var state = $.data (target, ' DataGrid ');
  32. var opts = state.options; var dc = STATE.DC;
  33. var view = this; Delete the Onloadsuccess event to prevent it from being triggered and back up to State.onloadsuccess
  34. state.onloadsuccess = opts.onloadsuccess; opts.onloadsuccess = function () {};
  35. Opts.finder.getRow = function (t, p) {
  36. var index = (typeof p = = ' object ')? P.attr (' Datagrid-row-index '): p; var row = $.data (t, ' DataGrid '). Data.rows[index];
  37. if (!row) {//What situation will not be taken? var v = $ (t). DataGrid (' Options '). View;
  38. row = V.rows[index-v.index]; }
  39. return row; };
  40. Dc.body1.add (dc.body2). empty ();
  41. This.rows = undefined; The need to draw the TR bound to view.rows on the THIS.R1 = THIS.R2 = []; VIEW.R1 and VIWE.R2 each hold a reference to the first TR and the last page tr
  42. Do not take it for granted, just bound to the event, when the first load of data, when exactly when the event is triggered?//This problem goes back to the LoadData method, each time after loaddata will be directly used Triggerhandler trigger scroll
  43. Dc.body2.unbind ('. DataGrid '). Bind (' Scroll.datagrid ', function (e) {if (state.onloadsuccess) {
  44. opts.onloadsuccess = state.onloadsuccess; Recover onloadsuccess Event state.onloadsuccess = undefined;
  45. } if (View.scrolltimer) {//clear Timer
  46. Cleartimeout (View.scrolltimer); }
  47. Delay 50 ms Execution View.scrolltimer = setTimeout (function () {
  48. Scrolling.call (view); }, 50);
  49. });
  50. function Scrolling () {if (dc.body2.is (': Empty ')) {//dc.body2 corresponds to the normal column data, if empty, the description has no data.
  51. Attempt to load data without data reload.call (this);
  52. } else {var firsttr = Opts.finder.getTr (target, This.index, ' body ', 2);
  53. var lasttr = opts.finder.getTr (target, 0, ' last ', 2); var headerheight = Dc.view2.children (' Div.datagrid-header '). Outerheight ();
  54. var top = firsttr.position (). Top-headerheight; var bottom = Lasttr.position (). Top + lasttr.outerheight ()-headerheight;
  55. if (Top > dc.body2.height () | | Bottom < 0) {
  56. Reload.call (this); } else if (Top > 0) {
  57. var page = Math.floor (this.index/opts.pagesize); This.getRows.call (this, target, page, function (rows) {
  58. THIS.R2 = THIS.R1; THIS.R1 = rows;
  59. This.index = (page-1) *opts.pagesize; This.rows = This.r1.concat (THIS.R2);
  60. This.populate.call (this, target); });
  61. } else if (Bottom < Dc.body2.height ()) {//need to load next page in case var page = Math.floor (this.index/opts.pagesize) +2;
  62. if (this.r2.length) {page++;
  63. } this.getRows.call (this, target, page, function (rows) {
  64. if (!this.r2.length) {this.r2 = rows;
  65. } else {this.r1 = THIS.R2;
  66. THIS.R2 = rows; This.index + = Opts.pagesize;
  67. } this.rows = This.r1.concat (THIS.R2);
  68. This.populate.call (this, target); });
  69. } }
  70. function Reload () {
  71. var top = $ (dc.body2). scrolltop ();//rolled-up height var index = math.floor (TOP/25);//gets rolled-up row index, such as: Roll up a row and half 37.5,index for 1
  72. var page = Math.floor (index/opts.pagesize) + 1;//Gets the number of pages, if 10 per page, rolled 262.5,page to 2
  73. This.getRows.call (this, target, page, function (rows) {This.index = (page-1) *opts.pagesize;// View.index is the index of the first row of page pages
  74. This.rows = Rows;//view.rows to store the TR THIS.R1 required to be painted = rows;
  75. THIS.R2 = []; This.populate.call (this, target);
  76. Dc.body2.triggerHandler (' Scroll.datagrid '); });
  77. } }
  78. },
  79. Getrows:function (target, page, callback) {var state = $.data (target, ' DataGrid ');
  80. var opts = state.options; var index = (page-1) *opts.pagesize;
  81. var rows = State.data.rows.slice (index, index+opts.pagesize); if (rows.length) {//This is the way that all data is loaded at once, you can extract the data directly from the local JavaScript array
  82. Callback.call (this, rows);
  83. } else {//lazy load mode var param = $.extend ({}, Opts.queryparams, {
  84. Page:page, Rows:opts.pageSize
  85. }); if (opts.sortname) {
  86. $.extend (param, {sort:opts.sortName,
  87. Order:opts.sortOrder});
  88. } if (Opts.onBeforeLoad.call (target, param) = = false) return;
  89. $ (target). DataGrid (' loading ');
  90. var result = Opts.loader.call (target, param, function (data) {$ (target). DataGrid (' loaded ');
  91. var data = Opts.loadFilter.call (target, data); Callback.call (Opts.view, data.rows);
  92. Opts.onLoadSuccess.call (target, data); }, function () {
  93. $ (target). DataGrid (' loaded '); Opts.onLoadError.apply (target, arguments);
  94. }); if (result = = False) {
  95. $ (target). DataGrid (' loaded '); }
  96. } },
  97. Populate:function (target) {
  98. var state = $.data (target, ' DataGrid '); var opts = state.options;
  99. var dc = STATE.DC; var rowHeight = 25;
  100. if (this.rows.length) {
  101. Opts.view.render.call (Opts.view, Target, dc.body2, false); Opts.view.render.call (Opts.view, Target, dc.body1, true);
  102. See, the scroll bar has so much space is how to achieve it? With the padding! Dc.body1.add (Dc.body2). Children (' table.datagrid-btable '). CSS ({
  103. Paddingtop:this.index*rowheight, Paddingbottom:state.data.total*rowheight-this.rows.length*rowheight-this.index *rowheight
  104. }); Opts.onLoadSuccess.call (Target, {
  105. Total:state.data.total, Rows:this.rows
  106. }); }
  107. } });

    The Virtualscrollview principle is to simulate the maximum data volume by setting up the upper and lower padding of Div, We only draw a little more than the visible part of the Treasyui Virtualscrollview support two ways: one is to request all the data at once The second is that each time Ajax to pageSize data Easyui the Virtualscrollview of the TR number is 2*pagesize (the first load exception, when only painting 1*pagesize tr) Easyui The Virtualscrollview view of the row height is mandatory as 25px, if you set a non-25px row height, this view will not work properly because only the 2*pagesize tr, so we dategrid height can not be set to more than 2*25* PageSize pixels, more than the words will cause the visible area is left white use the LoadData method to load the data loaddata the parameter does not need the total property, as long as the rows array can be, total within the loaddata automatically calculated

    For the previous points, we look at the source code in the comments I wrote, the foundation is poor, see a indefinitely on the line, the basis of good, the best to thoroughly study.

    Existing bug request background dead loop

    If it is a URL, the first time the data is not loaded, the background is constantly being requested. See the 146 line, if the callback function does not accept the rows, it should not trigger the Scorll event, because the scroll event will request background data, I have to add the conditions on the line:

      1. if (rows && rows.length > 0) {dc.body2.triggerHandler (' Scroll.datagrid ') ;
      2. Two requests background

        URL mode, if the background returned data is not enough to fill the table height, the background will be repeated (note that this place only repeats the request once, different from the first bug). The reason for this problem is also very simple, in fact, this situation, the DataGrid is a bit large, but the background and only a few data caused by only a few data, and this batch of data is not enough to fill the table visual area height. Let's add 122 lines to the call of the GetRows method:

        1. if (this.rows.length = opts.pagesize) {This.get Rows.call (this, target, page, function (rows) {
        2. if (!this.r2.length) {this.r2 = rows;
        3. } else {this.r1 = THIS.R2;
        4. THIS.R2 = rows; This.index + = opts.pagesize;
        5. This.rows = This.r1.concat (THIS.R2);
        6. this.populate.call (this, target);});
        7. This.rows is a group of rows that are currently drawn, and if rows are not pagesize large, then it is no longer necessary to request data.

          Virtualscrollview is a good optimization method, will be applied more and more widely, Easyui Virtualscrollview view Support editor I have to try, estimates are not supported, Interested students can go to research.

JQuery Easyui Datagrid virtualscrollview View Simple analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.