Vue.js实现多条件筛选、搜索、排序及分页的表格(3)

这里直接将各个变量动态化,再通过Table.vue中的input绑定v-model以及表头thead绑定@click事件来改变筛选的条件,就已经实现了大部分的搜索、过滤、分页功能。

表头改变sort排序我是通过以下代码实现的,方式可能不是太好,特此列出:

<thead> <tr> <th @click="sort = {key: 'ranking', val: -sort.val}">排名</th> <th @click="sort = {key: 'rating', val: -sort.val}">分数</th> <th>资料</th> <th>服务器</th> <th @click="sort = {key: 'weeklyRate', val: -sort.val}">本周战绩</th> <th @click="sort = {key: 'seasonRate', val: -sort.val}">赛季战绩</th> </tr> </thead>

可以看到,通过vue的filters功能,已经可以轻松完成我们的大部分功能,代码量极少。这也是vue2.0前瞻发布之后,提出废弃部分filters功能后许多人反应较为强烈的原因。但是如同作者在改动说明中所说,filters对于初学者来说不易理解,并且filters的功能都可以用computed属性进行更灵活、更好把控的实现。而且在一些复杂条件下,堆叠过滤器会造成一些额外的复杂性以及不方便之处。

那么何为复杂条件呢?例如我增添两个需求,一是按职业筛选玩家,而是筛选出一定分数以上的玩家,那么后者用filterBy就不太好实现了。我们需要将对分数段的过滤放在filters之前进行,但又要注意不破坏players数组本身。在实际完成时,会发现这个过程还是比较纠结的。

除此之外,我们还会发现分页中最重要的一个信息——总页数我们获取不到。因为vue并没有把一串过滤管道中产出的最终用于v-for的数组暴露出来,所以我们无法获得这个实际被循环的数组的长度。

在实际hack这些需求时,发现很容易与filters的执行顺序发生冲突,因此决定重新用computed属性来实现一遍所有功能,不借助自带的filters。

当然,在这一段的前半部分中,我们显而易见的感受到了来自filters的便利性。如果需求中filters可以满足,那么在1.x版本中使用filters还是十分明智的!

用computed属性完成需求

在Github仓库中,我用Table.vue.bak文件储存了之前一段中用filters实现的代码,方便与我们接下里的实现进行比较。

首先整理一下用computed属性来实现的思路:

首先要实现filterBy, orderBy, limitBy这三个filter的功能,上文中已经提到了他们的内部实现,所以分别用Array.filter, Array.sort和Array.slice重写一遍并不复杂。

说是computed属性实现,其实也还是只有players这个computed属性,只是在其内部执行了所有的过滤动作,我们实际是把各种过滤器的逻辑放置在各个method中。

不建议把各个过滤method写的过于抽象,因为就是内置filters高度抽象导致一些特殊需求无法实现,所以不妨就以最针对性的方式:一个method对应一种过滤。

在执行各个过滤method时,依然有最初提到的顺序带来的效率问题。因为vue牵一发而动全身的特性,任何一个过滤条件改变时,所有过滤method都会执行一遍,所以尽快用高效的过滤器缩短数组长度显得更为重要。

我尝试过通过watch属性实现最小化method调用,但无奈功力不够没能实现。同时我也认为前端处理大量数据的情况很少见,并且用第4点中的数据进行优化后,执行效率不算太低,所以没必要在这个方面做过多纠结。真有性能瓶颈时,从服务器端寻求解决会更简单。

注意:在实现各种过滤method时,建议阅读vue中filterBy, orderBy, limitBy三部分的实现源码,其本身对于数组的操作就有一些优化,非常值得学习。在一些特殊情况中,例如数组中大量相等值时,过于简单的sort function会导致执行步数激增,vue中的一些处理都予以了避免。

根据需求目标,我设置了以下这些method(顺序即为执行顺序):

classFilter:过滤玩家职业,通过item.classId === this.class进行判断,this.class绑定的是一个select控件。

queryFilter:匹配玩家姓名中的字段,通过item.name.indexOf(this.query)判断,this.query则绑定一个input控件。

ratingFilter:筛选玩家分数段,通过item.rating >= this.rating进行判断,this.rating绑定了一个类型为range的input控件,range的范围则是用computed属性进行计算。

sortTable:因为Array.sort进行的步数较多,所以放在数组被上述3个method处理的较短后进行。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzwxy.html