用法
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind
表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,例如:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Document</title>
- <script src="vue.js"></script>
- </head>
- <body>
- <div id="app"><p>{{no | add(100) }}</p></div>
- <script>
- debugger
- var app = new Vue({
- el:"#app",
- data:{no:123},
- filters:{
- add:function(val,i){return val+i}
- }
- })
- </script>
- </body>
- </html>
渲染结果为:

当我们在页面里输出某些数据,需要进行格式转换的时候可以用这个过滤器
源码分析
parse()解析模板时遇到文本时会执行parseText()函数,如下:
- function parseText ( //第8575行 解析模板时用于解析文本
- text,
- delimiters
- ) {
- var tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE;
- if (!tagRE.test(text)) { //匹配是否有表达式,比如:{{message}} 如果没有,则表示是纯文本节点,则直接返回不做处理
- return
- }
- var tokens = [];
- var rawTokens = [];
- var lastIndex = tagRE.lastIndex = 0;
- var match, index, tokenValue;
- while ((match = tagRE.exec(text))) { //用正则tagRE去匹配text,此时match就是text里的每个值,对于:{{item}}:{{index}}来说,match等于Array["{{item}}","item"] 、 Array["{{index}}","index"]
- index = match.index; //该数据的起始索引
- // push text token
- if (index > lastIndex) { //如果index大于lastIndex,表明中间还有一段文本,比如:{{item}}:{{index}},中间的:就是文本
- rawTokens.push(tokenValue = text.slice(lastIndex, index));
- tokens.push(JSON.stringify(tokenValue));
- }
- // tag token
- var exp = parseFilters(match[1].trim()); //调用parseFilters对match[1做解析] ;例如{{no | add(100) }},解析后的格式为:_f("add")(no,100)
- tokens.push(("_s(" + exp + ")"));
- rawTokens.push({ '@binding': exp });
- lastIndex = index + match[0].length; //设置下一次开始匹配的位置
- }
- if (lastIndex < text.length) {
- rawTokens.push(tokenValue = text.slice(lastIndex));
- tokens.push(JSON.stringify(tokenValue));
- }
- return {
- expression: tokens.join('+'), //拼凑成一个 表达式,例如:"_s(item)+":"+_s(index)"
- tokens: rawTokens //模板信息,例如[{@binding: "item"},":",{@binding: "index"}]
- }
- }
- parseFilters定义在6436行,就是解析每个字符,最后拼凑出一个_f的字符,例子中执行完后等于

最后执行render函数的时候会执行_f函数,也就是Vue内部的resolveFilter函数,如下:
- function resolveFilter (id) { //第3774行 过滤器对应的函数
- return resolveAsset(this.$options, 'filters', id, true) || identity //执行resolveAsset函数
- }
resolveAsset会获取对应资源(过滤器、组件、指令等),返回对应函数,如下:
- function resolveAsset ( //第1498行 options:Vue实例的$options对象 type:类型,比如:components、filters id:获取的ID
- options,
- type,
- id,
- warnMissing
- ) {
- /* istanbul ignore if */
- if (typeof id !== 'string') {
- return
- }
- var assets = options[type];
- // check local registration variations first
- if (hasOwn(assets, id)) { return assets[id] } //先从当前实例上找id
- var camelizedId = camelize(id);
- if (hasOwn(assets, camelizedId)) { return assets[camelizedId] } //将id转化为驼峰式后再找
- var PascalCaseId = capitalize(camelizedId);
- if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] } //如果还没找到则尝试将首字母大写查找
- // fallback to prototype chain
- var res = assets[id] || assets[camelizedId] || assets[PascalCaseId]; //最后通过原型来查找
- if ("development" !== 'production' && warnMissing && !res) {
- warn(
- 'Failed to resolve ' + type.slice(0, -1) + ': ' + id,
- options
- );
- }
- return res
- }
执行完后_f("add")(no,100)里的_f("add")就会变成app实例里的add过滤器对应的函数了