Vue源码阅读--过滤器

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

创建过滤器的方式

  1. Vue.filter('id',function(){}) 全局过滤器定义
  2. 组件中 filters : { 'id' : function(){} } 组件内部过滤器

源码分析

一、编译阶段

parse阶段

我们发现对于过滤器的使用方式有两种:

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

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

在parse处理开始节点的processAttrs() 中发现了 通过bindRE.test(name)去匹配响应式的属性,然后通过 parseFilters(value) 去解析值中的过滤器。

compiler\parser\filter-parser.js

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

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

如:

字符一个一个往后匹配 如果发现 ` " ' 说明在字符串中,那么直到找到下一个匹配的才结束, /一样 同时 匹配 () {} [] 这些需要两边相等闭合 那么 | 才有效, 最后一个条件排除 || 即可

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

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

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

生成

  1. 以前面的结果为exp , 发现存在 ( , 然后生成

2. 文本双花括号插值中 {{ message | capitalize }}

文本的处理是在 parse中的chars()方法 其中存在一个解析 {{}} 的方法 parseText()

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

render阶段

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

core\instance\render-helpers\resolve-filter.js

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

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

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

赶紧努力消灭 0 回复