Vue中过滤器(filter)的使用
我们想一下有methods为什么要有filter的存在呢,因为filter的实现效率比methods要高的多。
看一下官方定义:
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:
1. 局部过滤器(使用最频繁)
语法
- template
<div>{{ name | judgeRole }}</div>
//或者
<div v-bind:id="rawId | formatId"></div>
上面的过滤器经过一顿操作之后就会变成:_s(_f("capitalize")(message))。
_f:该函数其实就是resolveFilter的别名,作用是从_this.$options.filter找到过滤器并返回
_s:该函数就是toString函数的别名,作用是拿到过滤之后的结果并传递给toString()函数,结果会保存到VNode中的text属性,返回结果直接渲染视图
_f函数的原理
_f函数其实就是寻找过滤器的,如果找到过滤器就返回过滤器,找不到就返回与参数相同的值。它的代码其实很简单:
import {identity, resolveAssets} from 'core/util/index'export function resolveFilter(id){return resolveAssets(this.$options, 'filters', id, true) || identity
}
我们重点来看一下resolveAssets到底做了什么事情。
export function resolveAsset (options, type, id, warnMissing){if(typeof(id) !== 'string'){return}const assets = options[type]if(hasOwn(assets, id)) return assets[id]const camelizedId = camelize(id)if(hasOwn(assets, camelizedId)) return assets[camelizedId]const PascalCaseId = capitlize(camelizedId)if(hasOwn(assets, PascalCaseId)) return assets[PascalCaseId]//检查原型链const res assets[id] || assets[camelizedId] || PascalCaseIdif(process.env.NODE_ENV!=='production'&& warnMissing&&!res){warn('Fail to resolve' + type.slice(0,-1)+':'+id, options)}return res
}
其实它的寻找过程也很简单,主要是做了以下的操作(id是过滤器id):
1.判断过滤器id是否为字符串,不是则终止
2.用assets存储过滤器
3.hasOwn函数检查assets自身是否存在id属性,存在则返回
4.hasOwn函数检查assets自身是否存在驼峰化后的id属性,存在则返回
5.hasOwn函数检查assets自身是否存在将首字母大写后的id属性,存在则返回
6.如果还是没有,就是去原型链找,找不到就会打印警告
过滤器解析原理
我们想一下,解析器是怎么解析过滤器的语法?其实在vue内部专门有这么一个函数用来解析过滤器语法:parseFilters
它的原理就是解析过滤器列表,然后循环过滤器列表
并拼接字符串
。
- script
filter:{judgeRole(val) {if (val === '0') {return '平台'} else if (val === '1') {return '企业'} else if (val === '2') {return '企业用户'} else {return ''}}}
说明
- 过滤器函数中的
value
,就是|
前面的值,它相当于第一个参数 - 在过滤器函数中一定要返回一个值,他就是我们对格式处理后的结果
- 通俗的来讲,当为一个数据绑定一个过滤器后,每一次渲染这个数据的时候,他都会调用相应过滤器的函数
实战
使用vue-cli下载一个默认的项目,我使用vue/cli4
默认的目录如下
1.在components
文件夹下新建FilterLoc.vue
表示局部的过滤器,并写上如下代码,我们的目的是把sunwukong
首字母变成大写
<template><div>{{name | capitalize}}</div>
</template><script>
export default {data(){return {name:'sunwukong'}},filters:{//当value改变的时候,他会执行这个函数capitalize:function (value) {//一定要返回一个值才能在组件中正常显示if (!value) return ''value = value.toString()return value.charAt(0).toUpperCase() + value.slice(1)}}
}
</script>
2.我们在App.vue
中引入并映射成组件
<template><div><filter-loc></filter-loc></div>
</template><script>
import FilterLoc from '@/components/FilterLoc'
export default {components:{FilterLoc}
}
</script>
3.运行项目,观察效果,我们发下sunwukong
首字母已经大写
2. 全局过滤器
1.我们可以在入口文件定义全局过滤器,当然也可以是其他文件,这里我们把最后一个首字母变成大写
- main.js
/* 定义全局过滤器 */
Vue.filter('capitalize', function (value) {if (!value) return ''const length = value.length - 1value = value.toString()return value.slice(0,length) + value.charAt(length).toUpperCase()
})
2.在components
文件夹下新建FilterGlo.vue
表示使用全局过滤器,并写上如下代码,直接使用过滤器
<template><div>{{name | capitalize}}</div>
</template><script>
export default {data(){return {name:'zhubajie'}}
}
</script>
3.我们在App.vue
中引入并映射成组件,运行项目观察效果
说明
4. 其实刚刚我们定义了两个id
相同的过滤器,但是我们发现局部的并没有改变,于是我们就发现了,过滤器的优先级:局部的要比全局的优先级高;
3. 串联过滤器
语法
<div>{{ message | filterA | filterB }}</div>
- 后一个过滤器接收的参数为前一个参数的返回值
实战
1.在components
文件夹下新建FilterSer.vue
表示使用串联过滤器,并写上如下代码,直接使用全局过滤器(尾字母大写),和我们自定义的过滤器(首字母大写)
<template><div>{{name|initalWord|capitalize}}</div>
</template><script>
export default {data(){return {name:'shawujing'}},filters:{initalWord:function (value) {if (!value) return ''value = value.toString()return value.charAt(0).toUpperCase() + value.slice(1)}}
}
</script>
2.我们在App.vue
中引入并映射成组件,运行项目观察效果,我们发现两个选择器都使用上了
4. 过滤器的参数
语法
<div>{{ message | filterA('arg1', arg2) }}</div>
实战
- 在
components
文件夹下新建FilterParam.vue
表示使用过滤器参数,并写上如下代码,定义了一个过滤器,并传递了参数
<template><div>{{name|paramsFil('白骨精','白龙马')}}</div>
</template><script>
export default {data(){return {name:'师徒四人'}},filters:{paramsFil:function (value,arg1,arg2) {console.log(value,arg1,arg2)return value + arg1 + arg2}}
}
</script>
我们在App.vue
中引入并映射成组件,运行项目观察效果带上了所需要的参数。
- 通过
filterA('arg1', arg2)
传入的参数为过滤器的后两个参数
这个filter已经是非常全了,希望对于各位同仁有一定的帮助,面试如果这样回答关于filter的话,已经非常全了,因为里边包括了空间权重情况,多参数情况,多过滤情况,全面。另外预祝同仁工作顺利,家庭和睦。