关于2.4.3版本的table的一些bug还有功能的加强建议

讨论 已结 42 2617
岁月小偷
悬赏:80飞吻

一上来先跑个题[偷笑] ,刚好今天是俺加入社区的一周年,飞吻也刚好昨天也攒到了2w了小小纪念一下[嘻嘻]


2.4.0+的版本最大的亮点无疑就是table的加强,经过快速迭代发布的3个小版本之后,目前已经处理掉起初比较明显的一些槽点还有bug,但是目前还是有一些bug还有一些觉得可以强化的:
下文中的测试页面代码: https://pan.baidu.com/s/1OjwwVmjy02wRQ0rT1euLlQ 包括一个自己修改的2.4.3源码版的table.js。感兴趣的亲可以备份一下自己的table.js然后覆盖进去试试看。

※※更早
bug部分:
1,筛选列的时候total行没有对应的显示隐藏。
2,点击一个复选框checkbox监听里面的“操作行数据”为空的
功能加强部分:
1,筛选列支持设置hideable
2,筛选列的可选项中的文字显示优化
3,setColsWidth的一些调整
分享部分:
1,巧用parseData来让初始化的table选中某些行
2,应对工具栏的按钮很多老长老长挤压实际内容区域显示的一种思路

※※更新时间:2018年9月7日16:39:13
强化部分新增:
4,让table更优雅的reload

部分bug
1,筛选列的时候total行没有对应的显示隐藏。

审查下面的元素可以看到是因为下面td中的data-key设置错误,跟上面的实际的内容的td对比一下就知道了。
ps:这个data-key是新版本加进去的一个内容用标识列在table中的编号的,规则是:table的index-在cols第一层的下标-在cols第二层的下标。然后还有一个比较大的变化是列的样式的控制也更新了,不是以前的laytable-cell-tableIndex-fieldName||index这种情况,而是换成laytable-cell-dataKey这种组合,这个算是一个非常不错的改进,这样子后面即使字段设置中的field出现.或者[]也不会样式乱了,更加合理了。

修改方案:既然是data-key不对就找到这个生成统计行的代码把tableIndex给拼上去

最后效果:

2,点击一个复选框checkbox监听里面的“操作行数据”为空的

这个是因为这个回调的this的问题,原本this指向的是你点击的那个form给你生成的“复选框”,但是!如果点击之后会影响全选的状态的话,需要form.render一下,而且这个操作是在这个回调之前做的,所以render过后等于说前面点击的那个节点已经不复存在了或者说投胎转世了,只不过你看不到变化,没察觉到实际已经删除了然后生成了新的了这个过程。

修改方案:要么把更新渲染滞后,要么就换一个即使render也不会走丢的,实际上来说应该是后面这个方案要好一些。所以建议是把这两个this换成点击的时候的原始节点,这个不管如何form如何重新渲染就是稳稳当当的杵在那的。

最后效果:

ps:因为修改了this指向,所以要注意如果自己的代码里面在回调的是使用了这个this,要对应的调整一下,只要知道是原始节点就可以了,如果不修复,以前的代码中通过this想去找到它所处的tr啥的是找不到的了,也是有异常的,所以这个修改应该来说影响不是坏的。
功能加强部分
1,目前支持设置筛选列,那么一个很常用的逻辑就是部分是不可隐藏的,或者说不需要隐藏的,这个建议还有有一个配置,比如hideable来控制。
效果:

源码修改的地方有两处:
1-1,init的时候加多一个条件,等于说hideable如果为false即使你设置了这个字段hide也是白搭。可以理解为这个的优先级要更加高一点。

1-2,在构建筛选列的下拉选择的时候把不可隐藏的给设置成disabled,后面就无法点击隐藏了。

最后是测试的代码中相关的配置信息

2,筛选列的可选项中的文字,建议改成读取头部的text()而不是title的配置内容,不然title设置了html的话也会影响到这个筛选列的下拉显示,比如:

修改的地方:

效果:

测试的相关配置:

3,建议修改table中关于setColsWidth的一些设定,目前的情况是render或者reload的时候表头一开始是拧成一团的,等到数据来了渲染之后再变回正常的状态,看了一下原来是在success或者error或者data模式下的处理都是在差不多都要到done回调之前再执行,这个时机觉得太晚了,没必要,可以一开始就设置好样式后面填充数据表格节点就可以了了,

然后看到个更加神奇的事情是竟然把关掉loading的逻辑放在setColsWidth最后那里去做,这个感觉跟诡异,感觉像是setColsWidth之前会显示loading一样,实际是没有的,无端端把功能代码强行加到里面去这个感觉很怪异。

4,让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);
可能会有小伙伴会察觉,另外一个reload呢?返回实例中的那个reload,因为实在基本是弃用状态,所以也没有去整理,所以目前只改了table.reload这个,tableIns.reload这个还是原来的。
那么还能对以前的代码影响更小吗?能否做到只要更新了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']

一些分享
1,巧用parseData来让初始化的table选中某些行
2.4.0+版本终于把数据格式局限这个一直以来的问题给KO了,parseData的功能就是数据结构转换,将任意返回的数据结构组装成table能认得的格式返回给table,其实还带来了一个附带的功能,就是数据处理,也就是说它不仅仅只是在调整结构上有作用,只要你在返回之前,根据需要对数据进行处理,比如多选的默认选中,只要加上相关的属性就可以轻松的搞定。比如下面的处理

效果

实际上不建议在parseData里面这样子处理,因为无形中加了一些耦合性,最好的效果是parseData只处理数据结构转换,有另外的回调来处理数据返回成功之后,在实际渲染之前的一个数据加工的回调比如renderData之类的,但是无奈目前table的事件还会比较匮乏,不想改源码的基础上就可以这么利用parseData来做一些数据加工。
2,应对工具栏的按钮很多老长老长挤压实际内容区域显示的一种思路
工具栏太长内容区域被压榨的现象也是一直以来一个比较老大难的问题,比如上面看到的那些截图啥的,如果设置太短,会有...而且点击显示更多的时候弹出来的内容里面的按钮是点击不了的。这里提供一种可以动态的改变宽度的思路,就像折叠面板一样可以展开收起,效果如下:

测试代码中的表格配置:

动态改变列宽的方法封装:

PS: 实际加上上面这两个还不会有效果的,原因是table在调整列宽的时候不会对那些固定值的列重新调整,但是我那个方法就是想要调整设置中的这个宽度,让它重新调整,所以为了最大化的不要做无用功,只对明确告诉他我调整宽度了,table你给我重新修改一下样式,为了达到这个目的添加了一个新的配置widthChange,这个配置一开始不需要的,只有在用js修改了宽度想要调整的时候再给这列的配置加上就可以了,对应的源码修改一下如下。
回帖