过滤器,本质上就是函数。其作用在于用户输入数据后,它能够进行处理,并返回一个数据结果。
Vue.js与AngularJS中的过滤器语法有些相似,使用管道符( | )进行连接。
Vue.js支持在任何出现表达式的地方添加过滤器。除了Mustache风格还可以在绑定指令的表达式后使用。
<span v-text="message | uppercase"> {{ 'abc' | uppercase }} </span>
表达式的值可以根据用户的输入来动态改变,也可以像abc一样采用固定值。
过滤器可以接受参数,参数跟在过滤器后面,参数之间可以空格分隔。
{{ message | filterFunction 'arg1' arg2 }}
需要强调的是,过滤器函数将始终以表达式的值作为第一个参数。带引号的参数会被当做字符串处理,而不带引号的参数会被当做数据属性名来处理。这里message将作为第一个参数,字符串arg1作为第二个参数,表达式arg2的值在计算出来之后作为第三个参数传给过滤器。
( | ) 上一个命令的输出可以作为下一个命令的输入。
Vue.js 的过滤器支持链式调用,上一个过滤器的输出结果可以作为下一个过滤器的输入。
这种将各种功能相对独立的过滤器函数组合起来解决复杂数据处理的方式与软件工程的"高内聚,低耦合"设计思想有异曲同工之妙。用户可以非常灵活地对数据进行处理,获得想要的数据形式。
内置过滤器
仅针对英文字符串使用
1.capitalize : 过滤器用于将表达式的首字母转换为大写形式
2.uppercase : 过滤器用于将表达式中的所有字母转换为大写形式
3.lowercase : 过滤器用于将表达式中的所有字母转换为小写形式
json过滤器
Vue.js中的json过滤器本质上是 JSON.stringify() 的精简缩略版,可将表达式的值转换为JSON字符串。
json可以接受一个类型为Number的参数,用于决定转换后JSON字符串的缩进距离,如果不输入该参数,则默认为2
限制
Vue.js 内置了limitBy,filterBy,orderBy三个过滤器用于处理并返回过滤后的数组,比如与v-for搭配使用。注意,这三个过滤器所处理的表达式的值必须是数组,否则报错。
1.limitBy : 限制数组为开始的前N个元素,其中N由传入的第一个参数指定。第二个参数可选,用于指定开始的偏移量,默认为0,即不偏移。如果第二个参数为5,则表示以数组下标为5的地方开始计数。
<div v-for=" item in items | limitBy 10 "></div> //只显示开始的10个元素
<div v-for=" item in items | limitBy 10 5 "></div> //显示第5到15个元素
2.filterBy : 第一个参数可以是字符串或函数。过滤条件是:' string || function ' + in + 'optionKeyName ' (第70页)
<div v-for=" item in items | filterBy 'hello' "></div> //只显示包含hello字符串的元素
<div v-for=" item in items | filterBy 'hello' in 'name' "></div> //过滤器只在item对象的name属性中搜索hello。最好始终限制搜索范围,可以提高行性能与效率。
也可以在多个字段中进行搜索,字段与字段之间用空格分隔。
<div v-for=" item in items | filterBy 'hello' in 'name' 'nickname' "></div>
还可以将搜索字段存放在一个数组中,这样当修改字段时只需要修改数组就可以了,无需修改view层。
<div v-for=" item in items | filterBy searchText in fields "></div> // fields = [ 'fieldA','fieldB' ]
上面例子均使用了静态参数,当然也可以使用动态参数作为搜索目标或搜索字段。结合v-model,可以轻松的实现提示输入效果。
<div id="dynamic-filter-by">
<input v-model="name">
<ul>
<li v-for="user in users | filterBy name in 'name' ">
{{ user.name }}
</li>
</ul>
</div>
new Vue ({
el:'#dynamic-filter-by',
data:{
name:' ',
users: [
{ name:'Bruce' },
{ name:'Chuck' },
{ name:'Jackie' }
]
}
})
根据输入框中用户输入的数据,可以实时过滤出包含用户输入的字符串的数组元素,十分搞笑、简洁。动态参数作为搜索字段的方式与此类似。
如果filterBy的第一个数组是函数,则过滤器将根据函数的返回结果进行过滤。此时filterBy过滤器将调用JavaScript数组中内置的函数filter()对数组进行处理,待过滤数组中的每个元素都将作为参数输入并执行传入filterBy中的函数。只有函数返回结果为true的数组元素才符合条件并将存入一个新的数组,最终返回结果即为这个新的数组。
3.orderBy:过滤器的作用是返回排序后的数组。条件是:'string || array || function ' + 'order>=0 为升序 || order<0 为降序 '。第一个参数可以是数组,字符串或者函数。第二个参数order可选,决定结果为升序或降序排列,默认为1,即升序排列。
若输入参数为字符串,则可同时传入多个字符串为排序键名,字符串之间以空格分隔。
此时将排序键名按照顺序放入一个数组中,然后传入一个数组参数给orderBy过滤器即可。
当第一个参数为函数时,orderBy过滤器与JavaScript数组中内置的sort()函数表现一致。
注:事实上,当传入参数为字符串或者数组时,最终调用的也是sore()函数,只不过Vue.js提前做了一些处理,比如设置了默认的compare函数等,根据传入的compare函数进行排序。
currency过滤器
currency过滤器的作用是将数字值转换为货币形式输出。其第一个参数接受类型为String的货币符号,如果不输入,则默认为美元符号$。第二个参数接受类型为Number的小数位,如果不输入则默认为2。注意:如果第一个参数默认,而需要第二个参数修改小数位,则第一个参数不可省略,把默认的 '$' 写上。
debounce过滤器
debounce过滤器的作用是延迟处理器一定的时间执行。其接受的表达式的值必须为函数,因此其一般与v-on等指令结合使用。debounce接受一个可选的参数作为延迟时间,单位为毫秒。如果没有该参数,则默认时间为300毫秒。经过debounce包装的处理器在调用之后将至少延迟设定的时间再执行。如果延迟结束前再次调用,则延迟时长则重置为设定的时间。通常,在监听用户input事件时debounce过滤器比较有用,可以防止频繁调用方法。
<input @keyup=" onkeyup | debounce 500 ">
6.2自定义过滤器
Vue.js中自定义过滤器的语法与AngularJS在形式上相近,但是语法略有不同。
6.2.1 filter语法
在Vue.js中也存在一个全局函数Vue.filter用于构造过滤器:
Vue.filter ( ID,function () { } )
该函数接受两个参数,其中第一个参数为过滤器ID,作为用户自定义过滤器的唯一标识;第二个参数则为具体的过滤器函数。过滤器函数以值为参数,返回转换后的值。
1.单个参数
注册一个名为reverse的过滤器,作用是将字符串反转输出。代码如下:
Vue.filter ( 'reverse' ,function (value) {
return value.split(' ').reverse().join(' ');
})
<span v-text=" message | reverse "></span>
2.多参数
过滤器函数除了以值为参数外,还接受支持任意数量的参数,参数之间以空格分隔。
3.双向过滤器
上面的过滤器函数都是在Model数据输出到View层之前进行数据转化的,实际上Vue.js还支持把来自视图(input 元素)的值在写回模型前进行转化的,即双向过滤器。
Vue.filter( id,{
// model -> view
// read 函数可选
read:function(val){ },
// view -> model
// write 函数将在数据被写入Model之前调用
// 两个参数分别为表达式的新值和旧值
write:function(newVal,oldVal){
}
});
4.动态参数
注意,如果过滤器参数没有用引号包起来,则它会在当前vm作用域内动态计算。此外,过滤器函数的this始终指向调用它的vm。
6.2.2 教你写一个filter
之前的简单过滤器reverse已经实现
需要注意两点:
①需要给过滤器一个唯一的标识。如果用户自定义的过滤器和Vue.js内置的过滤器冲突,那么Vue.js内置的过滤器将被覆盖。如果注册后的和之前的冲突,会覆盖之前的。
②过滤器函数的作用是输入表达式的值,经过处理后输出。因此,定义的函数最好可以返回有意义的值。函数没有return语句不会报错,但是这样的过滤器没意义。
6.3 源码解析
6.3.1 管道实现
为了让过滤器的调用尽可能简单并且支持链式调用等特性,Vue.js主要借助了几个函数。
管道实现的原理是:Vue.prototype.$eval 接受类型为String的后跟过滤器及其参数的表达式(列如'message | filterExample argsl '),运用正则表达式检测传入的字符串中是否存在管道符( | ),如果存在,则调用parseDirective函数将传入的字符串整理输出为一个对象。
其中 parseDirective 调用了 pushFilter 和 processFilterArg 两个函数。前者的作用是将一个过滤器函数加上对象内的 filters 数组中;后者的作用是检查一个参数是否为静态参数,并且去掉静态参数上的引号。
在得到 parseDirective 处理好的对象之后,Vue.prototype.$eval 将调用 Vue.prototype._applyFilters 函数,该函数将表达式的值作为参数输入并依次调用 filters 数组中的过滤器函数,最后输出经过所有过滤器处理的数据结果,达到链式调用过滤器的效果。
6.4 常见问题解析
1.filterBy/orderBy 过滤后 $index 的索引
在使用 filterBy 或者 orderBy 对表达式进行过滤时,如果同时需要将 $index 作为参数,此时的 $index 将会根据表达式数组或对象过滤后的值进行索引。
2.自定义filter的书写位置
自定义 filter 可以写在全局的Vue下,也可以写在实例当中。二者本质并无区别,但是采用Vue.filter时,需要在实例化 Vue 对象前定义,否则自定义的filter将不起作用。