在Datagrid基础DOM结构的一文中,我对Datagrid组件的骨架做了很详细的描述。有了骨架还并不完整,还得有血有肉有衣服穿才行。强大的Datagrid组件允许我们自己定义如何在基础骨架上长出健壮诱人的身体,我们只要定义Datagrid的视图就可以实现。
在大多数情况下,我们并无特别要求,Datagrid给我们提供了默认的视图,默认视图被使用在90%以上的场景,所以对默认视图的分析显得非常有必要。注意视图里面定义了哪些接口,哪些方法,如果要自己写视图的话,最好把这些接口和方法都写齐全。话不多说,直接上代码(部分注释比较淫荡,未成年人轻绕行)
- varview={
- /**
- *填充表格主体数据(生成数据部分的各行tr)
- *@param{DOMobject}targetdatagrid宿主table对应的DOM对象
- *@param{DOMobject}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){
- vardata=$.data(target,"datagrid");
- varopts=data.options;
- varrows=data.data.rows;
- varfields=$(target).datagrid("getColumnFields",frozen);
- if(frozen){
- //如果grid不显示rownumbers并且也没有frozenColumns的话,直接退出。
- if(!(opts.rownumbers||(opts.frozenColumns&&opts.frozenColumns.length))){
- return;
- }
- }
- //定义表格字符串,注意这里使用了数组的join方式代替了传统的"+"运算符,在大多浏览器中,这样效率会更高些。
- varhtml=["<tableclass=\"datagrid-btable\"cellspacing=\"0\"cellpadding=\"0\"border=\"0\"><tbody>"];
- for(vari=0;i<rows.length;i++){
- //striped属性,用于设置grid数据是否隔行变色,当然了实现原理很简单。
- varcls=(i%2&&opts.striped)?"class=\"datagrid-rowdatagrid-row-alt\"":"class=\"datagrid-row\"";
- /**
- *表格的rowStyler属性用于处理数据行的css样式,当然了这个样式仅仅是作用于tr标签上。
- *这地方使用call了方法来设置上下文,如果rowStyler函数内部使用了this的话,则this指向datagrid的宿主table对应的DOM对象。
- */
- varstyle=opts.rowStyler?opts.rowStyler.call(target,i,rows[i]):"";
- varstyler=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"
- */
- varrowId=data.rowIdPrefix+"-"+(frozen?1:2)+"-"+i;
- html.push("<trid=\""+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(""));
- },
- /**
- *[renderFooterdescription]
- *@param{DOMobject}targetdatagrid宿主table对应的DOM对象
- *@param{DOMobject}container可能为dc.footer1或者dc.footer2
- *@param{boolean}frozen是否为frozen区
- *@return{undefined}未返回值
- */
- renderFooter:function(target,container,frozen){
- varopts=$.data(target,"datagrid").options;
- //获取footer数据
- varrows=$.data(target,"datagrid").footer||[];
- varcolumnsFields=$(target).datagrid("getColumnFields",frozen);
- //生成footer区的table
- varfooterTable=["<tableclass=\"datagrid-ftable\"cellspacing=\"0\"cellpadding=\"0\"border=\"0\"><tbody>"];
- for(vari=0;i<rows.length;i++){
- footerTable.push("<trclass=\"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{DOMobject}targetdatagrid宿主table对应的DOM对象
- *@param{array}fieldsdatagrid的字段列表
- *@param{boolean}frozen是否为冻结列
- *@param{number}rowIndex行索引(从0开始)
- *@param{jsonobject}rowData某一行的数据
- *@return{string}单元格的拼接字符串
- */
- renderRow:function(target,fields,frozen,rowIndex,rowData){
- varopts=$.data(target,"datagrid").options;
- //用于拼接字符串的数组
- varcc=[];
- if(frozen&&opts.rownumbers){
- //rowIndex从0开始,而行号显示的时候是从1开始,所以这里要加1.
- varrowNumber=rowIndex+1;
- //如果分页的话,根据页码和每页记录数重新设置行号
- if(opts.pagination){
- rowNumber+=(opts.pageNumber-1)*opts.pageSize;
- }
- /**
- *先拼接行号列
- *注意DOM特征,用zenCoding可表达为"td.datagrid-td-rownumber>div.datagrid-cell-rownumber"
- */
- cc.push("<tdclass=\"datagrid-td-rownumber\"><divclass=\"datagrid-cell-rownumber\">"+rowNumber+"</div></td>");
- }
- for(vari=0;i<fields.length;i++){
- varfield=fields[i];
- varcol=$(target).datagrid("getColumnOption",field);
- if(col){
- varvalue=rowData[field];
- //获取用户定义的单元格样式,入参包括:单元格值,当前行数据,当前行索引(从0开始)
- varstyle=col.styler?(col.styler(value,rowData,rowIndex)||""):"";
- //如果是隐藏列直接设置display为none,否则设置为用户想要的样式
- varstyler=col.hidden?"style=\"display:none;"+style+"\"":(style?"style=\""+style+"\"":"");
- cc.push("<tdfield=\""+field+"\""+styler+">");
- //如果当前列是datagrid组件保留的ck列时,则忽略掉用户定义的样式,即styler属性对datagrid自带的ck列是不起作用的。
- if(col.checkbox){
- varstyler="";
- }else{
- varstyler="";
- //设置文字对齐属性
- 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("<divstyle=\""+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("<inputtype=\"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>");
- }
- }
- //返回单元格字符串,注意这个函数内部并未把字符串放到文档流中。
- returncc.join("");
- },
- /**
- *刷新行数据,只有一个行索引(从0开始),调用的updateRow方法,这里直接跳过。
- *@param{DOMobject}targetdatagrid实例的宿主table对应的DOM对象
- *@param{number}rowIndex行索引(从0开始)
- *@return{undefined}未返回数据
- */
- refreshRow:function(target,rowIndex){
- this.updateRow.call(this,target,rowIndex,{});
- },
- /**
- *刷新行数据,该接口方法肩负着同步行高,重新计算和布局grid面板等重任
- *@param{DOMobject}targetdatagrid实例的宿主table对应的DOM对象
- *@param{number}rowIndex行索引(从0开始)
- *@param{jsonobject}行数据
- *@return{undefined}未返回数据
- */
- updateRow:function(target,rowIndex,row){
- varopts=$.data(target,"datagrid").options;
- varrows=$(target).datagrid("getRows");
- $.extend(rows[rowIndex],row);
- varstyle=opts.rowStyler?opts.rowStyler.call(target,rowIndex,rows[rowIndex]):"";
- functionupdateTableRow(frozen){
- varfields=$(target).datagrid("getColumnFields",frozen);
- //这个地方查找grid的数据主体表格(可能包含冻结列对应的主体表格和普通列对应的主体表格)
- //getTr这个函数,我在博客上介绍过,请参考:http://www.easyui.info/archives/396.html
- vartr=opts.finder.getTr(target,rowIndex,"body",(frozen?1:2));
- varchecked=tr.find("div.datagrid-cell-checkinput[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-checkinput[type=checkbox]")._propAttr("checked",true);
- }
- };
- //更新冻结列对应的行
- updateTableRow.call(this,true);
- //更新普通列对应的行
- updateTableRow.call(this,false);
- //重新布局表格面板
- $(target).datagrid("fixRowHeight",rowIndex);
- },
- insertRow:function(target,rowIndex,row){
- varstate=$.data(target,"datagrid");
- //options
- varopts=state.options;
- //documentofdatagrid
- vardc=state.dc;
- vardata=state.data;
- //兼容无效的rowIndex,默认设置为在最后一行追加
- if(rowIndex==undefined||rowIndex==null){
- rowIndex=data.rows.length;
- }
- //为啥不跟上面的条件并到一起,真是蛋疼
- if(rowIndex>data.rows.length){
知识推荐
- curl 区分https/http
- HDU-1061-Rightmost Digit (快速幂模板)
- [JSOI2008]球形空间产生器
- 再有人问你Netty是什么,就把这篇文章发给他
- JS采用正则表达式获取地址栏参数
- CSS ... 文本溢出用省略号代替
- thinkphp5 自定义验证码使用
- 三、hibernate中持久化类的使用
- 关于 pyspider Web预览界面太小的解决方法
- php 设计模式之适配器模式
- jsp隐式对象
- 创建 WEB 项目
- Apache + mod_wsgi部署webpy应用
- 编译安装PHP7及扩展
- 360大牛带你横扫PHP职场 全面解读PHP面试
- canvas toDataURL() 方法如何生成部分画布内容的图片
- 开发.NET Core NuGet包并实现CI/CD
- Caffe学习记录(十二) ICNet分割网络学习二
我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8
不良信息举报平台
互联网安全管理备案
Copyright 2023 www.wodecom.cn All Rights Reserved