Vue源码阅读--过滤器

原创 黎云锐 教程 前端 7561阅读 12 天前 举报

过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:

创建过滤器的方式
Vue.filter('id',function(){}) 全局过滤器定义
组件中 filters : { 'id' : function(){} } 组件内部过滤器
源码分析
一、编译阶段
parse阶段
我们发现对于过滤器的使用方式有两种:

在属性中 v-bind:id="xxx | filterA"
在文本双花括号插值中 {{xxx | filterA | filterB(arg1,arg2)}}

  1. 属性中 v-bind:id="xxx | filterA"

解析过滤器的方法其实很简单:

将属性的值从前往后开始一个一个匹配,关键符号 : "|" 并排除 ""、 ''、 ``、 //、 || (字符串、正则)中的管道符号 '|' 。
如:

<div v-bind:id="message + 'xxx|bbb' + (a||b) + cccc | filterA | filterB(arg1,arg2)"></div>
复制代码
字符一个一个往后匹配 如果发现 说明在字符串中,那么直到找到下一个匹配的才结束, /一样 同时 匹配 () {} [] 这些需要两边相等闭合 那么 | 才有效,最后一个条件排除 || 即可

所以上面直到遇到 第一个正确的 | ,那么前面的表达式 并存储在 expression 中,后面继续匹配再次遇到 | ,那么此时 expression有值, 说明这不是第一个过滤器 pushFilter() 去处理上一个过滤器
/**
生成过滤器的 表达式字符串

如上面的
exp = message
filters = ['filterA','filterB(arg1,arg2)']
第一步 以exp 为入参 生成 filterA 的过滤器表达式字符串 _f("filterA")(message)
第二步 以第一步字符串作为入参 生成第二个过滤器的表达式字符串 _f("filterB")(_f("filterA")(message),arg1,arg2)

此时 exp = message + 'xxx|bbb' + (a||b) + cccc , filter = filterA

继续判断 过滤器是否存在 (), 此时不存在, 那么filter就是名称 第一个入参就是前面的 exp。
生成

"_f("filterA")(message + 'xxx|bbb' + (a||b) + cccc)"

以前面的结果为exp , 发现存在 ( , 然后生成
"_f("filterB")(_f("filterA")(message + 'xxx|bbb' + (a||b) + cccc),arg1,arg2)"

  1. 文本双花括号插值中 {{ message | capitalize }}
    文本的处理是在 parse中的chars()方法 其中存在一个解析 {{}} 的方法 parseText()

发现 其也是通过const exp = parseFilters(match[1].trim()) 去处理 {{}}中的额过滤器。

render阶段
我们发现在编译节点如果遇到过滤器 会将其编译成 _f(){}的表达式

其还是通过resolveAsset去获取 vm.$options的filters中相同的过滤器

然后将 _f("filterA")(message + 'xxx|bbb' + (a||b) + cccc ),arg1,arg2 作为入参。

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复