国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

jQuery EasyUI框架中的Datagrid數據表格組件結構詳解

2019-11-20 09:44:46
字體:
來源:轉載
供稿:網友

基礎DOM結構
什么叫“完整的基礎DOM結構”,這里“基礎”的意思是指這個結構不依賴具體數據,不依賴Datagrid的view屬性,只要存在Datagrid實例就會存在這樣的基礎DOM結構;而“完整”的意思是指在凍結列,凍結行,標題,footer,分頁這些功能塊都存在時候的DOM結構。

要搞清楚Datagrid的工作原理,這個DOM結構必須要爛熟于胸的,我們直接來看這個“基礎完整DOM結構”是什么樣子的:

<!-- datagrid的最外層容器,可以使用$(target).datagrid('getPanel')或者$.data(target,'datagrid').panel得到這個DOM對象,這個DOM上其實承載了panel組件-->   <div class="panel datagrid">     <!-- datagrid的標題區域容器,對應于panel組件的header部分,可以使用$(target).datagrid('getPanel').panel('header')得到這個DOM對象-->     <div class="panel-header">       <div class="panel-title"></div>       <div class="panel-tool"></div>     </div>     <!-- datagrid的主體區域容器,對應于panel組件的body部分,可以使用$(target).datagrid('getPanel').panel('body')得到這個DOM對象-->     <div class="datagrid-wrap panel-body">     <!--工具欄-->     <div class="datagrid-toolbar"></div>       <!-- datagrid視圖部分的容器,這是datagrid組件DOM結構的核心,其基礎視圖結構跟datagrid的view屬性無任何關系。-->       <!-- 對應dc.view -->       <div class="datagrid-view">         <!-- div.datagrid-view1負責展示凍結列部分(包含行號或者frozenColumns)的數據-->         <!-- 對應dc.view1 -->         <div class="datagrid-view1">           <!--列標題部分-->           <div class="datagrid-header">             <!-- 對應dc.header1 -->             <div class="datagrid-header-inner">               <!--樣式里有htable關鍵字,h代表header的意思-->               <table class="datagrid-htable">                 <tbody>                   <tr class="datagrid-header-row"></tr>                 </tbody>               </table>             </div>           </div>           <!--列數據部分-->           <div class="datagrid-body">             <!-- 對應dc.body1 -->             <div class="datagrid-body-inner">               <!--frozenRows部分(有數據才會有這個table,故不屬于基礎DOM結構),固定行是1.3.2版本之后才加的功能,注意datagrid-btable-frozen關鍵樣式,btable代碼body table的意思-->               <table class="datagrid-btable datagrid-btable-frozen"></table>               <!--普通rows部分(有數據才會有這個table,故不屬于基礎DOM結構)-->               <table class="datagird-btable"></table>             </div>           </div>           <!--footer部分-->           <div class="datagrid-footer">             <!-- 對應dc.footer1 -->             <div class="datagrid-footer-inner">               <!--ftable代表footer table的意思-->               <table class="datagrid-ftable"></table>             </div>           </div>         </div>         <!-- div.datagrid-view2負責展示非凍結列部分的數據,大家注意到凍結列和普通列視圖是分開的,也就是說凍結列和普通列是在不同表格中展示的,這樣會產生一個問題,那就是兩個表格行高之間的同步問題。-->         <!-- 對應dc.view2 -->         <div class="datagrid-view2">           <!--列標題部分-->           <div class="datagrid-header">             <!-- 對應dc.header2 -->             <div class="datagrid-header-inner">               <table class="datagrid-htable">                 <tbody>                   <tr class="datagrid-header-row"></tr>                 </tbody>               </table>             </div>           </div>           <!--列數據部分,注意這里并無datagrid-body-inner這個子元素,而凍結列對應的body卻是有的,這個是細微區別-->           <!-- 對應dc.body2 -->           <div class="datagrid-body">             <!--frozenRows部分有數據才會有這個table,故不屬于基礎DOM結構,固定行是1.3.2版本之后才加的功能,-->             <table class="datagrid-btable datagrid-btable-frozen"></table>             <table class="datagrid-btable"></table>           </div>           <!--footer部分-->           <div class="datagrid-footer">             <!-- 對應dc.footer2 -->             <div class="datagrid-footer-inner">               <table class="datagrid-ftable"></table>             </div>           </div>         </div>       </div>       <!--分頁部分-->       <div class="datagrid-pager pagination"></div>     </div>   </div>

對于這個DOM結構,我在html代碼里面已經做了簡單說明,這里提一下綁定于Datagrid宿主table上的對象的dc屬性,這個dc屬性存儲了對DOM結構里不同部分的引用,獲取dc屬性的方法:

$.data(target,'datagrid').dc;

而dc屬性跟DOM的對應關系,我也在html中做了詳細注釋,請大家自行查看,這些都是我們深入認識Datagrid組件的基礎。

默認視圖分析
上面對Datagrid組件的骨架做了很詳細的描述。有了骨架還并不完整,還得有血有肉有衣服穿才行。強大的Datagrid組件允許我們自己定義如何在基礎骨架上長出健壯誘人的身體,我們只要定義Datagrid的視圖就可以實現。

在大多數情況下,我們并無特別要求,Datagrid給我們提供了默認的視圖,默認視圖被使用在90%以上的場景,所以對默認視圖的分析顯得非常有必要。注意視圖里面定義了哪些接口,哪些方法,如果要自己寫視圖的話,最好把這些接口和方法都寫齊全。

var view = {    /**    * 填充表格主體數據(生成數據部分的各行tr)    * @param {DOM object} target  datagrid宿主table對應的DOM對象    * @param {DOM object} container 數據主體容器。包含兩個可能的值,即:    * 1.frozen部分body1,對應的DOM對象為:div.datagrid-view>div.datagrid-view1>div.datagrid-body>div.datagrid-body-inner    * 2.常規部分body2,對應的DOM對象為:div.datagrid-view>div.datagrid-view2>div.datagrid-body    * @param {boolean} frozen  是否是凍結列    * @return {undefined}      未返回值    */   render: function(target, container, frozen) {      var data = $.data(target, "datagrid");      var opts = data.options;      var rows = data.data.rows;      var fields = $(target).datagrid("getColumnFields", frozen);      if(frozen) {        //如果grid不顯示rownumbers并且也沒有frozenColumns的話,直接退出。        if(!(opts.rownumbers || (opts.frozenColumns && opts.frozenColumns.length))) {          return;        }      }      //定義表格字符串,注意這里使用了數組的join方式代替了傳統的"+"運算符,在大多瀏覽器中,這樣效率會更高些。      var html = ["<table class=/"datagrid-btable/" cellspacing=/"0/" cellpadding=/"0/" border=/"0/"><tbody>"];      for(var i = 0; i < rows.length; i++) {        //striped屬性,用于設置grid數據是否隔行變色,當然了實現原理很簡單。        var cls = (i % 2 && opts.striped) ? "class=/"datagrid-row datagrid-row-alt/"" : "class=/"datagrid-row/"";        /**        * 表格的rowStyler屬性用于處理數據行的css樣式,當然了這個樣式僅僅是作用于tr標簽上。        * 這地方使用call了方法來設置上下文,如果rowStyler函數內部使用了this的話,則this指向datagrid的宿主table對應的DOM對象。        */       var style = opts.rowStyler ? opts.rowStyler.call(target, i, rows[i]) : "";        var styler = style ? "style=/"" + style + "/"" : "";        /**        * rowId:行的唯一標示,對應于tr的id屬性,其由以下幾部分組成:        * 1.字符竄常量:"datagrid-row-r";        * 2.全局索引index:該索引值從1開始遞增,同一個datagrid組件實例擁有唯一值,如果同一頁面內有多個datagrid實例,那么其值從1遞增分配給每個datagrid實例;        * 3.凍結列標識frozen:該標識用于標示是否是凍結列(包含行號和用戶指定的frozenColumns),"1"代表凍結列,"2"代表非凍結列;        * 4.行數索引:該值才是真正代表“第幾行”的意思,該值從0開始遞增        * 如頁面內第一個datagrid實例的非凍結列第10行數據的rowId為"datagrid-row-r1-2-9"        */       var rowId = data.rowIdPrefix + "-" + (frozen ? 1 : 2) + "-" + i;        html.push("<tr id=/"" + rowId + "/" datagrid-row-index=/"" + i + "/" " + cls + " " + styler + ">");        /**        * 調用renderRow方法,生成行數據(行內的各列數據)。        * 這里的this就是opts.view,之所以用call方法,只是為了傳參進去。這里我們使用this.renderRow(target,fields,frozen,i,rows[i])來調用renderRow方法應該也是可以的。        */       html.push(this.renderRow.call(this, target, fields, frozen, i, rows[i]));        html.push("</tr>");      }      html.push("</tbody></table>");      //用join方法完成字符創拼接后直接innerHTML到容器內。      $(container).html(html.join(""));    },    /**    * [renderFooter  description]    * @param {DOM object} target  datagrid宿主table對應的DOM對象    * @param {DOM object} container 可能為dc.footer1或者dc.footer2    * @param {boolean} frozen  是否為frozen區    * @return {undefined}      未返回值    */   renderFooter: function(target, container, frozen) {      var opts = $.data(target, "datagrid").options;      //獲取footer數據      var rows = $.data(target, "datagrid").footer || [];      var columnsFields = $(target).datagrid("getColumnFields", frozen);      //生成footer區的table      var footerTable = ["<table class=/"datagrid-ftable/" cellspacing=/"0/" cellpadding=/"0/" border=/"0/"><tbody>"];      for(var i = 0; i < rows.length; i++) {        footerTable.push("<tr class=/"datagrid-row/" datagrid-row-index=/"" + i + "/">");        footerTable.push(this.renderRow.call(this, target, columnsFields, frozen, i, rows[i]));        footerTable.push("</tr>");      }      footerTable.push("</tbody></table>");      $(container).html(footerTable.join(""));    },    /**    * 生成某一行數據    * @param {DOM object} target  datagrid宿主table對應的DOM對象    * @param {array} fields  datagrid的字段列表    * @param {boolean} frozen  是否為凍結列    * @param {number} rowIndex 行索引(從0開始)    * @param {json object} rowData 某一行的數據    * @return {string}     單元格的拼接字符串    */   renderRow: function(target, fields, frozen, rowIndex, rowData) {      var opts = $.data(target, "datagrid").options;      //用于拼接字符串的數組      var cc = [];      if(frozen && opts.rownumbers) {        //rowIndex從0開始,而行號顯示的時候是從1開始,所以這里要加1.        var rowNumber = rowIndex + 1;        //如果分頁的話,根據頁碼和每頁記錄數重新設置行號        if(opts.pagination) {          rowNumber += (opts.pageNumber - 1) * opts.pageSize;        }        /**        * 先拼接行號列        * 注意DOM特征,用zenCoding可表達為"td.datagrid-td-rownumber>div.datagrid-cell-rownumber"        */       cc.push("<td class=/"datagrid-td-rownumber/"><div class=/"datagrid-cell-rownumber/">" + rowNumber + "</div></td>");      }      for(var i = 0; i < fields.length; i++) {        var field = fields[i];        var col = $(target).datagrid("getColumnOption", field);        if(col) {          var value = rowData[field];          //獲取用戶定義的單元格樣式,入參包括:單元格值,當前行數據,當前行索引(從0開始)          var style = col.styler ? (col.styler(value, rowData, rowIndex) || "") : "";          //如果是隱藏列直接設置display為none,否則設置為用戶想要的樣式          var styler = col.hidden ? "style=/"display:none;" + style + "/"" : (style ? "style=/"" + style + "/"" : "");          cc.push("<td field=/"" + field + "/" " + styler + ">");          //如果當前列是datagrid組件保留的ck列時,則忽略掉用戶定義的樣式,即styler屬性對datagrid自帶的ck列是不起作用的。          if(col.checkbox) {            var styler = "";          } else {            var styler = "";            //設置文字對齊屬性            if(col.align) {              styler += "text-align:" + col.align + ";";            }            //設置文字超出td寬時是否自動換行(設置為自動換行的話會撐高單元格)            if(!opts.nowrap) {              styler += "white-space:normal;height:auto;";            } else {              /**              * 并不是nowrap屬性為true單元格就肯定不會被撐高,這還得看autoRowHeight屬性的臉色              * 當autoRowHeight屬性為true的時候單元格的高度是根據單元格內容而定的,這種情況主要是用于表格里展示圖片等媒體。              */             if(opts.autoRowHeight) {                styler += "height:auto;";              }            }          }          //這個地方要特別注意,前面所拼接的styler屬性并不是作用于td標簽上,而是作用于td下的div標簽上。          cc.push("<div style=/"" + styler + "/" ");          //如果是ck列,增加"datagrid-cell-check"樣式類          if(col.checkbox) {            cc.push("class=/"datagrid-cell-check ");          }          //如果是普通列,增加"datagrid-cell-check"樣式類          else {            cc.push("class=/"datagrid-cell " + col.cellClass);          }          cc.push("/">");          /**          * ck列光設置class是不夠的,當突然還得append一個input進去才是真正的checkbox。此處未設置input的id,只設置了name屬性。          * 我們注意到formatter屬性對datagird自帶的ck列同樣不起作用。          */         if(col.checkbox) {            cc.push("<input type=/"checkbox/" name=/"" + field + "/" value=/"" + (value != undefined ? value : "") + "/"/>");          }          //普通列          else {            /**            * 如果單元格有formatter,則將formatter后生成的DOM放到td>div里面            * 換句話說,td>div就是如來佛祖的五指山,而formatter只是孫猴子而已,猴子再怎么變化翻跟頭,始終在佛祖手里。            */           if(col.formatter) {              cc.push(col.formatter(value, rowData, rowIndex));            }            //操,這是最簡單的簡況了,將值直接放到td>div里面。            else {              cc.push(value);            }          }          cc.push("</div>");          cc.push("</td>");        }      }      //返回單元格字符串,注意這個函數內部并未把字符串放到文檔流中。      return cc.join("");    },    /**    * 刷新行數據,只有一個行索引(從0開始),調用的updateRow方法,這里直接跳過。    * @param {DOM object} target  datagrid實例的宿主table對應的DOM對象    * @param {number} rowIndex 行索引(從0開始)    * @return {undefined}     未返回數據    */   refreshRow: function(target, rowIndex) {      this.updateRow.call(this, target, rowIndex, {});    },    /**    * 刷新行數據,該接口方法肩負著同步行高,重新計算和布局grid面板等重任    * @param {DOM object} target  datagrid實例的宿主table對應的DOM對象    * @param {number} rowIndex 行索引(從0開始)    * @param {json object} 行數據    * @return {undefined}     未返回數據    */   updateRow: function(target, rowIndex, row) {      var opts = $.data(target, "datagrid").options;      var rows = $(target).datagrid("getRows");      $.extend(rows[rowIndex], row);      var style = opts.rowStyler ? opts.rowStyler.call(target, rowIndex, rows[rowIndex]) : "";       function updateTableRow(frozen) {        var fields = $(target).datagrid("getColumnFields", frozen);        //這個地方查找grid的數據主體表格(可能包含凍結列對應的主體表格和普通列對應的主體表格)        //getTr這個函數,我在博客上介紹過,請參考:http://www.easyui.info/archives/396.html        var tr = opts.finder.getTr(target, rowIndex, "body", (frozen ? 1 : 2));        var checked = tr.find("div.datagrid-cell-check input[type=checkbox]").is(":checked");        //這里調用了renderRow方法來重新獲取當前行的html字符串        tr.html(this.renderRow.call(this, target, fields, frozen, rowIndex, rows[rowIndex]));        tr.attr("style", style || "");        //更新的時候保留checkbox狀態(包含兩層信息:一是有ck列;二是ck列被之前就被選中)        if(checked) {          tr.find("div.datagrid-cell-check input[type=checkbox]")._propAttr("checked", true);        }      };      //更新凍結列對應的行      updateTableRow.call(this, true);      //更新普通列對應的行      updateTableRow.call(this, false);      //重新布局表格面板      $(target).datagrid("fixRowHeight", rowIndex);    },    insertRow: function(target, rowIndex, row) {      var state = $.data(target, "datagrid");      //options      var opts = state.options;      //document of datagrid      var dc = state.dc;      var data = state.data;      //兼容無效的rowIndex,默認設置為在最后一行追加      if(rowIndex == undefined || rowIndex == null) {        rowIndex = data.rows.length;      }      //為啥不跟上面的條件并到一起,真是蛋疼      if(rowIndex > data.rows.length) {        rowIndex = data.rows.length;      }      /**      * 下移rows      * @param {boolean} frozen 是否為frozen部分      * @return {undefined}    無返回值      */     function moveDownRows(frozen) {        //1:凍結列部分;2:普通列部分        var whichBody = frozen ? 1 : 2;        for(var i = data.rows.length - 1; i >= rowIndex; i--) {          var tr = opts.finder.getTr(target, i, "body", whichBody);          //注意這地方設置了tr的"datagrid-row-index"和"id"屬性          tr.attr("datagrid-row-index", i + 1);          tr.attr("id", state.rowIdPrefix + "-" + whichBody + "-" + (i + 1));          //計算行號          if(frozen && opts.rownumbers) {            //因rowIndex從0開始,以及須插入位置以下的tr要統一下移,所以新行號為i+2            var rownumber = i + 2;            //有分頁的話,行號還要加上分頁數據            if(opts.pagination) {              rownumber += (opts.pageNumber - 1) * opts.pageSize;            }            tr.find("div.datagrid-cell-rownumber").html(rownumber);          }        }      };      /**      * 插入了,要插兩個地方的哦(如果你是男人,你可以淫蕩地笑一下)      * @param {boolean} frozen 是否是frozen部分      * @return {undefined}    未返回值      */     function doInsert(frozen) {        var whichBody = frozen ? 1 : 2;        //這行代碼,不知道是干嘛的,怕插入得太快而早早繳械,所以才故意拖延時間的么?        var columnFields = $(target).datagrid("getColumnFields", frozen);        //構造新插入行的id屬性        var trId = state.rowIdPrefix + "-" + whichBody + "-" + rowIndex;        var tr = "<tr id=/"" + trId + "/" class=/"datagrid-row/" datagrid-row-index=/"" + rowIndex + "/"></tr>";        if(rowIndex >= data.rows.length) {          //如果已經有記錄,則插入tr即可          if(data.rows.length) {            //嗯哼,getTr的這個用法不多哦,未傳入行索引,第三個參數為"last",隨便的意淫一下就知道是獲取最后一行了            //然后再在最后一行后插入一行,注意了,這里用的后入式            opts.finder.getTr(target, "", "last", whichBody).after(tr);          }          //如果表格尚無記錄,則要生成表格,同時插入tr          else {            var cc = frozen ? dc.body1 : dc.body2;            cc.html("<table cellspacing=/"0/" cellpadding=/"0/" border=/"0/"><tbody>" + tr + "</tbody></table>");          }        }        //在rowIndex + 1前準確無誤地插入,注意了,這里是前入式。        else {          opts.finder.getTr(target, rowIndex + 1, "body", whichBody).before(tr);        }      };      //下移frozen部分      moveDownRows.call(this, true);      //下移普通列部分      moveDownRows.call(this, false);      //插入frozen區      doInsert.call(this, true);      //插入普通區      doInsert.call(this, false);      //總數加1      data.total += 1;      //維護data.rows數組,這地方是插入一個數組元素了      data.rows.splice(rowIndex, 0, row);      //刷新,其中包含了重新布局grid面板等復雜得一筆的操作      //插入本是件很簡單愉快的事情,可是你得為其后果負上沉重的代價      this.refreshRow.call(this, target, rowIndex);    },    /**    * 刪除行接口    * @param {DOM object} target datagrid實例的宿主table對應的DOM對象    * @param {number} rowIndex 行索引    * @return {undefined}    未返回值    */   deleteRow: function(target, rowIndex) {      var state = $.data(target, "datagrid");      var opts = state.options;      var data = state.data;       function moveUpRows(frozen) {        var whichBody = frozen ? 1 : 2;        for(var i = rowIndex + 1; i < data.rows.length; i++) {          var tr = opts.finder.getTr(target, i, "body", whichBody);          //"datagrid-row-index"和"id"屬性減一          tr.attr("datagrid-row-index", i - 1);          tr.attr("id", state.rowIdPrefix + "-" + whichBody + "-" + (i - 1));          if(frozen && opts.rownumbers) {            var rownumber = i;            if(opts.pagination) {              rownumber += (opts.pageNumber - 1) * opts.pageSize;            }            tr.find("div.datagrid-cell-rownumber").html(rownumber);          }        }      };      //移除行      opts.finder.getTr(target, rowIndex).remove();      //上移frozen區      moveUpRows.call(this, true);      //上移普通區      moveUpRows.call(this, false);      //記錄數減一      data.total -= 1;      //維護data.rows數據      data.rows.splice(rowIndex, 1);    },    /**    * 默認的onBeforeRender事件 為空    * @param {DOM object} target datagrid實例的宿主table對應的DOM對象    * @param {array} rows 要插入的數據    * @return {undefined}    默認未返回值    */   onBeforeRender: function(target, rows) {},    /**    * 默認的onAfterRender 隱藏footer里的行號和check    * @param {DOM object} target datagrid實例的宿主table對應的DOM對象    * @return {undefined}    未返回值    */   onAfterRender: function(target) {      var opts = $.data(target, "datagrid").options;      if(opts.showFooter) {        var footer = $(target).datagrid("getPanel").find("div.datagrid-footer");        footer.find("div.datagrid-cell-rownumber,div.datagrid-cell-check").css("visibility", "hidden");      }    }  }; 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 西昌市| 石河子市| 咸丰县| 溧水县| 宁海县| 宜宾市| 东丽区| 拜城县| 商南县| 满城县| 辽宁省| 晋江市| 淳安县| 图们市| 吉林省| 万盛区| 桃江县| 福建省| 中方县| 宝应县| 宁强县| 绥棱县| 当阳市| 抚州市| 得荣县| 昌江| 卢湾区| 龙游县| 瑞昌市| 拉孜县| 瑞丽市| 台山市| 安阳县| 黄浦区| 石泉县| 双江| 行唐县| 莱西市| 潍坊市| 安溪县| 报价|