layui表格数据变更的一种处理方式

表格数据变更,一般包括几个内容:新增、修改、删除、移动,开发中经常会面临的一个问题就是变更之后如何将数据同步到节点上,一直以来个人的建议还是利用表格重载,不管是url模式的还是data模式的实际都是需要重载,url重载自然会重新请求后台得到最新的数据,data模式一般就是对data的操作,之后重新以新的data去渲染出来。

同时会考虑的是如何尽量减少请求,可能感受最深的就是update操作,为了要更新这一条记录而重载整个表格,请求一遍数据感觉划不来,那么一般来说就可以利用表格的tool事件中的obj.update这个方法去更新。

不过具体使用中就会发现其诸多的不足的地方,本文就是主要针对这些不足进行一个处理给出一个tablePlug.update的方法,然后进而衍生出add和remove和move,同时新增了更新统计行数据的方法。

测试页面: 综合测试页面 流加载表格测试页面 定时刷新表格测试页面

一、update

正如上面说的obj.update(data)有诸多限制,优点上来说就是用最小的修改代价,实现了数据的更新,他就更新参数中的data中的键的数据,不会整个行更不会整个table的节点更新;缺陷是底层的实现逻辑有点问题:

1、是通过遍历data,更新缓存cache中对应的记录的key的value,然后根据cols的配置信息更新td的内容,但是如果是想要更新toolbar列的话就没戏,目前解析的只有templet的,所以如果想要更新toolbar的话基本就只能设置成templet,而且要给这个列添加一个field,才有理论上的可能。

2、toolbar列即使加了field改成templet也未必能更新过来,因为内部的实现逻辑是先判断原始的data是否有这个key,所以如果field命名是原始的data里面没有的,后面用obj.update也更新不进去的,这个是一个比较大的限制。

因为拿我们项目来说,后台给我们的数据如果原始的记录里面没有这个key的值他不会给一个key: ''的,那么后面要想利用obj.update这个key就变得不可能,除非利用parseData在渲染之前对后台给的数据做一个人工的初始化把对应的key添加上,但是可想而知有多麻烦。

3、数据他是一个一个更新进去,然后更新一个值就更新对应的td,但是这个就存在另外一个风险了,就是遍历对象他是无序的,比如update{a: 1, b:2},如果a字段的cols中会用到b字段的值做一个处理再显示出来。

那么如果遍历顺序是先更新a的值,然后就开始更新a的td的内容,这个时候cache中b的值还是旧的不是你要更新进去的2,等到更新了b字段了他又不能说检测到其他字段有使用了这个字段会去再次更新对方的内容,这就导致了a出来的结果还是错的。

4、更新了统计列的某一个值统计行的对应数据没有重新计算。

总结的来说就是,obj.update实现的还是太过理想化太过简单,一条记录从数据上来说每个key是独立的这个没什么问题,但是到页面显示就不然了,因为页面的内容它不一直是单个字段的简单值显示,还会进行一些特殊处理。

所以需要一个templet来转化,来自定义,所以有可能一个td里面会用到多个字段这个很正常,工具列的按钮也会根据数据的状态去决定部分按钮是否显示等等。

所以个人认为要更新这个数据不能是一个独立的小单元的更新,而是先update这一行的数据然后在update这一行,而不是遍历被update的key一个个更新,再往大了看,实际这个表的记录也是一个整体。

也是不能说你改了这条记录其他的记录必定是不变的,不排除某个字段的td他会根据当前页面的同一个field做了什么处理现实,比如统计行,所以目前的思路就是直接将值先update到cache中,然后再调用table内部的渲染tr td的内容。

大致的代码:

1579059007896296.png

前面是针对参数做了一些处理让参数更加灵活,最关键的是后半部分的更新cache的部分,还要一个最关键的renderData的方法:

1579059017111371.png

他的作用就是将cache中的数据重新解析渲染一遍,同时针对是否是移动数据还有默认点击那一条记录的处理,但是核心是渲染cache,调用table.js内部的renderData。

使用场景:

1、知道当前编辑修改的是那一条记录,可以看看一个最常用的场景就是点击编辑弹出一个form然后修改提交,完成之后希望尽量不要重新请求接口更新到data和页面中去,

gif很不好录,自己使用测试的例子里面的编辑按钮测试效果即可

调用的更新数据的形式是:

tablePlug.update(表格实例的id, 当前tr的index, newData)

1579059027272235.png

2、不知道当前的trIndex的情况下update某一条记录的话,必须有一个限制就是必须是有主键的表格,并且更新的数据中必须包含主键的字段,不然你也不知道更新的到底是哪条记录。

tablePlug.update('demo', {id: 10002, username: '贤心'});

3、一次性更新多条记录,这个参数trIndex就没有意义了,加了也没用,因为是更新多条记录,所以可以这么写

tablePlug.update('demo', [{id: 10002, username: '贤心'}, {id: 10006, username: '小偷', age: 18, sign: '大叔'}]);

这个测试页面可以看看头部toolbar中的“积分清零”还有“女性积分加100”这两个测试按钮以及背后的事件执行的方法

4.png

4、更加任性的,只要传入一个tableId,update会将当前按照cache中的数据给渲染一次,这个是非常实用的,比如如果你觉得我update中的逻辑针参数对cache的修改的逻辑不满意可以自己用自己觉得更好的方法去处理cache,最后执行一下tablePlug.update('demo')就好了,提供更高的自由度,和拓展的可能性。

二、addData

addData添加的记录是已经请求接口完成返回的数据记录,本质上来说就是不一样的,所以不要混淆。

具体addData的代码:

1579059045223457.png

data模式的话,实际也是往data里面添加一些记录,然后也是再reload一下。

 // 添加单条记录:
tablePlug.addData ('demo', {id: newId, username: '甲'});
// 添加多条记录
tablePlug.addData ('demo', [{id: newId1, username: '乙'},{id: newId2, username: '丙'}]);

关于addData的有一个比较综合的例子可以看看利用table的data模式怎么跟流加载配合使用,弄成一个流加载的表格

https://sun_zoro.gitee.io/layuitableplug/testTableFlow

三、del

新增和删除实际个人建议还是reload比较稳妥,不管是url还是data模式都是,所以删除对应的处理方式也跟新增实际差不多,只不过删除麻烦一点的就是data模式要在原始的记录里面去删除指定的记录。

而且有可能开启了复选的状态记忆删除了就要将关于他的状态给调整一下;还是为了使用更方便,参数同样做了处理,

1、删除指定的下标的数据,可以查看表格行的toolbar中的删除按钮的监听处理,但是注意,如果表格是url的模式,目前测试页面写的都是json文件,所以reload也不会有效果的。

所以要测试请在data模式的测试,不用纠结这个,url的如果是实际的服务接口的话是后台返回数据,一般删除成功了后面查询是不会再出来的,除非后台接口有问题。

6.png

2,删除指定的一些记录,这个一般有两种形式,但是要求一样就是必须是有主键的表格

// id集合
tablePlug.del('demo', [1,2,3,4]);
// 对象数组
tablePlug.del('demo', [{id: 1, name: 'name1'}, {id:2}, {id:4}]);

根据得到哪种数据比较方便就用哪种形式,可以参考测试页面的批量删除的处理方式

1579059068662686.png

四、move

这个处理基本跟update差不多,将数据在cache中调整位置,然后调用一下组件内部的renderData的方法让他重新渲染出来就好

8.png

然后为了使用方便衍生出来一个上移跟下移的方法

9.png

效果

10.gif

理论上利用一些拖拽事件或者其他的插件在事件中调用一下tablePlug.move('demo', form, to);就能够实现顺序的任意改变了

限制:注意!这个只是针对数据移动,不会有单条数据记录的变动,如果原始的数据里面有点击了排序,那么移动之后默认是会去掉这个排序的状态了的,因为移动之后很可能就不能满足当前的排序规则了,所以建议在使用移动的时候不要跟sort搭配,如果有sort而且所谓的移动是会发起请求改变数据的,那么这个建议还是使用请求接口得到两个新的数据然后用update去更新他们的位置。

五、renderTotal

在记录更新之后,如果存在统计行有需要统计的列,那么值一般也要跟着变,另外一个更加重要的作用就是可以自定义统计规则,而不是自带的求和,可以自定一定计算的函数,或者可以直接类似templet一样的去自定义返回的内容,包括异步的去读取想要显示的数据。

代码大概如下:

11.png

从实现代码可以看出就是给cols的字段配置新增一个totalFormat的设置,可以设置一个规则如果不设置的话就是sum(目前也只是添加了sum,其他的规则后面会加入或者自己加入,比如平均。

最大最小不过个人觉得主要意义是可以自定义方法,这个才是实用常用的),也可以设置一个方法,如果不是异步的可以直接把结果返回,如果是需要异步的那么也可以在得到最终想要的结果的时候执行:

tablePlug.renderTotal(tableId, field, res);

比如下面的:

12.png

平时实用的话不是都要自己去调用的,在插件内部已经在renderDone回调里面会去执行他了:

13.png

参数也是比较自由,不同的组合会有不同的效果,

// 触发更新某个表格的所有列的统计数据
renderTotal(tableId);
// 触发更新某个表格的某个字段的数据
renderTotal(tableId, fieldName);
// 更新某个表格的某个字段的统计数据为value
renderTotal(tableId, fieldName, totalValue);

六、refresh

之前做过一个智能reload的修改,即在执行table.reload的时候会根据传过去的option来判断只是重新请求数据还是需要重载一下,个人觉得效果可以了。

不过对于有强迫症(有追求)的小伙伴来说,在一些场景下还是不够好,就是那些定时刷新的,表现就是一方面滚动条会回到top:0,left:0,还有其他的比如鼠标在操作分页组件的时候会觉得失去焦点,新增一个tablePlug.refresh来试一试能否满足要求。

先看效果:

14.gif

事件背后做的事情:

15.png

表格config:

16.png

背后的实现思路

17.png

修改table的Class.prototype.pullData支持refresh模式

renderData的时候根据是否refresh去做一些细节的处理,还有一个限定就是返回的数据中关于总数应该是不变的,如果发生了改变,那么还是会renderData,会重新渲染page组件。

另外一个限制就是这种refresh的表格不建议再加什么按钮呀edit呀,因为它一直会在变,基本主要就是用来做一个单纯用来显示用的表格,比如一些经常变化的数据,访问人次,股票动态之类的。

使用:

// 启动表格demo的自动刷新功能,500毫秒一次
tablePlug.refresh('demo', 500);
// 取消表格demo的自动刷新
tablePlug.refresh('demo', false);
// 停止所有已开启自动刷新的表格的自动刷新
tablePlug.refresh(false);

推荐文章
layui兼不兼容ie8?

layui兼不兼容ie8?layui兼容ie8,layui兼容人类正在使用的全部浏览器(IE6/7除外),可作为PC端后台系统与前台界面的速成开发方案。layui(谐音:类UI)是一款采用自身模块规范

Layui的简易入门教程

获得layui后,将其完整地部署到你的项目目录(或静态资源服务器),你只需要引入下述两个文件:./layui/css/layui.css ./layui/layui.js //提示:如果是采用非模块化

项目中如何优雅地使用函数 layui.define

前言:1、如果你深刻理解并合理运用layui.define,那么本篇对你来说有点浪费时间了。2、如果你对于“Javascript模块化开发”听都没听过,更别说还要理解它。那么建议可以先在网络上找找什么

layui是什么时候开发的?

layui(谐音:类UI)是一款采用自身模块规范编写的前端UI框架,遵循原生HTML/CSS/JS的书写与组织形式,门槛极低,拿来即用。其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从核心代码到

layui input只读属性是什么?

layuiinput只读属性是什么?layuiinput只读属性是readonly。readonly属性规定输入字段为只读。只读字段是不能修改的。不过,用户仍然可以使用tab键切换到该字段,还可以选中

vue.js和layui一样么?

vue.jsVue(读音/vjuː/,类似于view)是一套用于构建用户界面的渐进式JavaScript框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,方

前端layui框架快速上手

一、介绍在使用layui之前,我们先要了解一下layui是什么?我觉得用作者贤心的一句话来概括就好了:为后端程序员设计的前端框架。更加详细的描述是:这是一个封装了各种css和js、Ajax等等的前端框

layui如何关闭弹出层?

layui可以使用closeAll关闭弹出层,如果不指向层类型的话,它会销毁掉当前页所有的layer层。我们可以使用下面的方法关闭指定层:layer.closeAll();//疯狂模式,关闭所有层la

浅谈layui表单中的inline和block

layui表单中的inline和block:block:block元素会独自占一行,多个block元素各自新起一行,默认情况下,block元素宽度自动填充其父元素宽度 单行输入框 验证必填项

layui如何获取table某一行的值?

layui中可以使用table.checkStatus('ID')方法获取table某一行的值,其中ID为基础参数。【自动化渲染】……【方法渲染】table.render({//其它参数省略 id:'

layui中的layer怎么进行宽高设置?

layui中的layer模块可以使用area设置宽高。类型:String/Array,默认:'auto'在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area:'500px',

浅谈layui中table.render的使用(附代码)

layui框架提供了丰富的内置模块,他们皆可通过模块化的方式按需加载,其中包括:layer、layDate、layPage、laytpl、table等。本篇文章给大家浅谈一下layui中table.r

layui是什么软件?

layui不是软件,它是一款采用自身模块规范编写的前端UI框架,遵循原生HTML/CSS/JS的书写与组织形式,门槛极低,拿来即用。其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从核心代码到AP

layui开源么?

layui是免费开源的,layui是开源的模块化前端UI框架,而layAdmin和layIm是付费授权的。layui是一款采用自身模块规范编写的前端UI框架,遵循原生HTML/CSS/JS的书写与组织

详解layui.layer独立组件

layer至今仍作为layui的代表作,她的受众广泛并非偶然,而是这五年多的坚持,不断完善和维护、不断建设和提升社区服务,使得猿们纷纷自发传播,乃至于成为今天的Layui最强劲的源动力。目前,laye

layui时间控件清空之后无法正常使用怎么办?

解决layui时间控件清空之后无法正常使用的问题,以及时间范围的选择。共有两种解决方式:方式一(layui1.x):html代码: js代码:varstart={ istime:tru

layui的模块是什么意思?

layui是一款采用自身模块规范编写的前端UI框架,遵循原生HTML/CSS/JS的书写与组织形式,门槛极低,拿来即用。其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从核心代码到API的每一处细

layui怎么固定表格的表头?

步骤:1、设置两个table,第一个table有thead没有tbody,第二个table有tbody没有table;2、第二个table需要一个div包住,并设置宽高,可用绝对布局3、tr下的th和

layui表格中怎么显示图片?

layui的表格使用还是非常简单的,layui文档中已经非常详细,下面直接上代码了1、jsp代码 发布Banner 2、然后是js代码layui.use('table',function()

layui登录后token问题详解

layui是一个非常简单且实用的后台管理系统搭建框架,里面的插件丰富使用简单,只需要在原有基础上进行修改即可,但是在数据处理方面略显薄弱,内置的jquery在实际过程中略显不足,若是能添加内置的mvc