以下文章将解读并展示如何使用Vue属性监听和计算属性的方法,实现一个列表过滤。
列表过滤01
{{index+1}}
{{person.name}}
{{person.sex}}
{{person.age}}
要实现如上图所示的效果,大致可以分为两步:
- 第一步是获取文本框中的值。
- 第二步是使用文本框中的值去匹配过滤已有的数据源。
一开始,我自己的思路是通过键盘事件来获取input中的输入值的,比如keydown,这么做可能能够实现获取input值的目标,无论按下什么键都会触发,这似乎不符合预期;真实的预期是:当input中的值产生变化的时候,才需要新的值,然后根据新的值去进行过滤。
既是input标签,而且需要获取变化的值,v-model应该比较合适。于是就有了如下的代码:
使用v-model绑定input中的value与Vue实例keyword属性,这样视图变化,属性keyword属性数据也会变化。
与此同时,使用属性监听,来监听keyword值的变化,就有了如下的代码:
以上的代码确实实现了列表过滤的功能,可是也出现了一些问题,如下:就是每命中检索过滤一次,persons源数据就会变少,直至最后persons中无一条数据。我们希望每次都是从persons源数据中去匹配过滤,优化的代码如下:
{{index+1}}
{{person.name}}
{{person.sex}}
{{person.age}}
两个地方的变化,一是给Vue实例新增了一个属性filterPersons,用于放置每次命中过滤的数据。
data:{
keyword:'',
persons:[
{id:'001', name:'马冬梅', sex:'女', age:18},
{id:'002', name:'周冬雨', sex:'女', age:19},
{id:'003', name:'周杰伦', sex:'男', age:20},
{id:'004', name:'温兆伦', sex:'男', age:40},
],
filterPersons:[]
}
二是v-for循环的数据源的变化,变为新增的那个属性filterPersons,这样每次展示的就是命中的数据。
{{index+1}}
{{person.name}}
{{person.sex}}
{{person.age}}
但如此仍然出现了一些问题,如下:
就是初始化的时候,看不到文本框下可供检索的对象列表,这个也不是所预期的,经过优化的代码如下:
不适用属性监听的简写形式,而是采用原始的写法,并添加上了immediate:true的配置,表示初始化的时候就执行一次监听,如此就可以实现本文开头所需要的效果:
紧接着上述内容,为什么让监听方法handler在初始化的时候就可以展示所有的可检索项?主要是因为indexOf这个方法。
通过测试我们可知,indexOf这个方法可以找出对应字符在字符串中的索引位置,如果找不到则返回“-1”,找到了则返回字符在对应位置上的索引。
有一个特别的字符就是空字符串,如果是空字符串,那么返回的也是“0”,跟字符串中首个字符返回的值是一样的,都是“0”。
watch:{
keyword:{
immediate:true,
handler(newValue){
this.filterPersons = this.persons.filter((person)=>{
return person.name.indexOf(newValue) !== -1;
})
}
}
}
所以在以上代码中,当设置immediate:true的时候,就是初始化的时候,使用空字符串进行一次匹配,因为返回的结果是“0”,其不等于“-1”,结果为true,所以返回了所有源数据persons的数据给filterPersons,就可以看见input下展示的所有源数据。
真是妙不可言呐!!!
列表过滤-计算属性实现01
{{index+1}}
{{person.name}}
{{person.sex}}
{{person.age}}
计算属性依赖Vue实例data中的属性数据,当keyword的发生改变的时候,filterPersons这个计算属性就会重新再计算一次,相比属性监听,不需要再额外新增和维护属性filterPersons,并且也无需单独监听keyword属性。
当计算属性和监听属性都能实现的时候,我们优先选择计算属性的方式去实现。
需要实现如下的升降序的效果:
效果分析:应该是对已经查询到的数据进行排序,而不是对源数据。比如:通过“冬”查询到了马冬梅和周冬雨两个人,此时如果点击年龄升序,则,年龄最小的在前,年龄最大的在后。
而如果是通过“伦”搜索到温兆伦和周杰伦,此时如果是年龄降序,则温兆伦在最前面,而周杰伦在最后面,如下图所示:
过滤排序实现的代码实现如下:
列表过滤-计算属性实现01
{{index+1}}
{{person.name}}
{{person.sex}}
{{person.age}}