table 如何更优雅的 reload

讨论 已结 精帖
130 11023
岁月小偷
悬赏:50飞吻
更新于2018年11月5日11:47:18
这个帖子是在2.4.3的版本上修改的,目前最新版本来到2.4.5了所以对应的也给reload的问题整理了一下,重新发了一个帖子: table如何更优雅的reload(第二版)
午休大放送,一直以来表格的重载经常被人诟病说会闪体验不好,想要做成点击底下laypage模块一样的效果,甚至有比较极端的说reload这样子的效果是个bug之类的。实际上要理解重载跟重新请求数据这两的区别,reload定义为重载,可以对里面的设置进行修改重载整个table视图,那么干掉原始节点重新生成新的节点这个应该是没有什么异议的,特别是异步请求的时候而且没有设置高度的时候,就会觉得闪的厉害的情况。比较懒,之前的处理方式一般就是定一个高度,也会变得不那么闪,但是新版本新加了头部工具栏之后就迫使不得不破这个问题了。

那么,个人看法,一般的解决思路有两种:

第一种,不要一开始就清空,而是等到后面内容全部组装ok了再覆盖进去,实际应该有一定的作用,但是效果估计也还是会看到“闪”的效果,然后新版本的比如头部按钮区域的有输入框啥的,重载之后还是会重新构建了里面的内容,然后以前输入的值就over了。

第二种,把重载和重新请求数据分开,做到跟点击分页相似,但是实际是有区别的,点击分页不会涉及到其他的比如接口变化,传参变化等,所以它可以做的非常简单,但是重新请求数据这个就不是那么简单处理了,还得考虑让它能够修改参数。这个能做出来就基本可以达到只是重新请求数据然后更新td的内容还有分页的内容。
说了这么多文字了,估计耐心要耗尽。先来个最终效果图吧,因为方式一不是最好的直接弃用,采用方式二达到了下面的效果。

可能觉得没看出啥,实际上有一个比较明显的就是工具栏input里面的输入没有被清空,没有被重新建,而且其实我是短时间内连续点击重载表格不下10次的,也不会看到页面“闪”的感觉,第一次重载因为是条数变少了所以内容区域变小了,这个是正常的,因为没有设置高度,它就是根据实际的内容来的,没有那么多了自然会收起来。
对比一下原始的感受一下吧。

重点的来了,如何实现?
上面也介绍了,方法一行不通的,所以采用方法二,将重载和重新请求数据分开,这个一开始觉是添加一个request的方法。跟reload区分开,但是后面一想,为了达到更小的修改代码的成本,决定还是对reload的方法进行改造,让他既支持重载又支持重新请求数据,那么一般来说就是添加多一个参数,好了下面废话不多说直接上修改代码的截图,里面的注释大概就是思路了,帖子最后会提供测试的代码还有table.js的下载地址。
源码修改的地方
1,thisTable 添加一个存储所有实例的变量

2,创建实例的时候将对应的实例保存起来

3,定义一个当前组件使用的跟数据接口相关的参数数组,还有重写reload

修改完毕之后如何使用?这个其实很简单,主要你在认为不需要重载的时候,以前发的reload还是那样子写,只不过多加一个参数,就变成了重新请求的模式了。然后如果还是重载比如你要修改工具条toolbar或者啥的涉及到改变table的组织结构的话就还是以前的老套路,两个参数就行了。具体看下面示例截图。

然后还有一个情况如果你查询条件啥的都没有变,只是重新查一下当前的这个表格,那么可以写成下面的
table.reload(tableId, true);
最后是测试代码和修改过的table.js的下载链接: https://pan.baidu.com/s/1OjwwVmjy02wRQ0rT1euLlQ
可能会有小伙伴会察觉,另外一个reload呢?返回实例中的那个reload,因为实在基本是弃用状态,所以也没有去整理,所以目前只改了table.reload这个,tableIns.reload这个还是原来的。
※更新于:2018年9月7日15:47:53 那么还能对以前的代码影响更小吗?能否做到只要更新了table.js的逻辑其他的业务代码不需要任何修改就能够做到reload的时候自动识别出是重载或者重新请求数据呢?
思路就是全权交给reload来处理,当然这里有个分岔口,以上的修改,能够做到的是明确指定是哪种方式,而且比如指定了重新请求那么即使你的参数里面多写了一些其他的限定范围外的属性也会被干掉,不会造成干扰,这个算是个优点,所以上面的那种方法,可以说有两个有点,一个是可以明确指定,第二个是指定了设置也会进行监控过滤,缺点是:需要调整业务代码把以前写的需要换成重新请求数据形式的reload都改一遍。下面是一个可以完全不修改以前业务代码的逻辑,让reload自己来判断是哪一种方式的实现,优点很明显,以前的代码不需要任何变动而且后面的也是,当然这个是建立一个认识就是完全依赖reload里面传过去的那个options来断定,而没有说自己强制指定某种方式的支持。后面说的这个算是个缺点吧。关键看能否接受这个认识了。
智能选择reload的方式的源码修改,前面几个修改跟上面那种方式一样,只有最后的reload重写这部分有区别

这样子修改了之后你原先的业务代码就可以不做任何修改就能够支持特定情况下只是重载数据,然后其他的情况就是重载表格
table.reload(tableId, {toolbar: false, {page: {curr: 1}}, where:{}});    // 重载表格
table.reload(tableId, {{page: {curr: 1}}, where:{}}); // 重新请求数据
※条件约束是reload的第二个参数里面不要出现下方数组成员以外的配置信息就是重新请求数据,但凡出现任何一个其他的,就是重载表格。
约束数组:['url', 'method', 'where', 'contentType', 'headers', 'parseData', 'request', 'response', 'data', 'page']
※ 发现了一个漏网的属性initSort,

※更新于2018年9月10日16:43:56,感谢@福尔摩凯 的情况反馈,以上的修改如果出现查询reload的时候出现没有数据的情况下,后面如果有数据了会出现右固定失效的情况,这个是因为以前的逻辑每次render()出来这个table的时候会判断是否有数据,没有数据的时候就会把固定列remove掉,这个在以前reload都重载整个表格的时候是没有问题的,因为他下次reload的时候会再次构建固定列的模块,但是修改成reload支持只request的话这块逻辑就得对应的变动一下了,修改如下。

更新于
感谢@捕刺客打刺客 @红茶绿茶 两位同学提出来的这个帖子修改中出现的问题,主要表现是:如果接口出现返回的状态码异常或者接口异常的情况下,后面再次reload之后成功了之后会出现一个问题就是实体的内容没有了的情况。这个主要是因为以前reload都是重构,所以源代码里面的部分处理是直接覆盖掉laymain里面的内容,laymain本来里面有table tbody,如果是重载每次都是重新新建,但是如果要使用重新请求的方式来更新里面的内容,这一块就不能这么覆盖了,所以如果按照以上的方式对table进行了改造,那么必须处理一下这些细节的问题。
修改地方:
修改1

修改2

修改3

修改4

更新于2018年10月8日14:37:05
感谢@yutons 的bug反馈,就是页面一开始正常然后遇到接口异常或者状态码不对的情况下左固定的内容没有刷新和影藏的情况。这个还是细节处理的确实,因为原来的逻辑是reload都是重构,也就是说跟render其实没有特别大的本质区别,然后以前的逻辑因为重载的时候table等于一开始都是一个新生的,但是重新请求等于是有历史记录一样的不是新生的节点,基于这个考虑在交易返回,即使接口异常了,或者状态码异常之类的,都按照一次空数据的形式render一次啊,后面再对实际的返回信息进行展示,这个觉得应该可以理解的,但是原有的逻辑是判断到没有数据只是做了一些置空的操作,不会走实际的内容render,所以导致了上面提到的bug。修改如下:

最后的测试效果:
回帖