# 1. 前言

过滤器在我们日常开发中应该算是一个非常常用的功能了,它经常会被用来格式化模板中的文本。过滤器可以单个使用,也可以多个串联一起使用,还可以传参数使用。那么在Vue中过滤器是如何工作的呢?其内部原理是怎样的?Vue又是如何识别出我们所写的过滤器的?接下来,我们将从源码角度出发,探究过滤器内部的工作原理,分析其工作流程,揭开它神秘的面纱。

# 2. 用法回顾

在介绍过滤器内部原理之前,我们先根据官方文档来回顾一下过滤器的使用方法。

# 2.1 使用方式

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

<!-- 在双花括号中 -->
{{ message | capitalize }}

<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
1
2
3
4
5

# 2.2 过滤器的定义

你可以在一个组件的选项中定义本地的过滤器:

filters: {
  capitalize: function (value) {
    if (!value) return ''
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)
  }
}
1
2
3
4
5
6
7

也可以在创建 Vue 实例之前使用全局APIVue.filter来定义全局过滤器:

Vue.filter('capitalize', function (value) {
  if (!value) return ''
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})
1
2
3
4
5

当全局过滤器和局部过滤器重名时,会采用局部过滤器。

# 2.3 串联过滤器

过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。在上述例子中,capitalize 过滤器函数将会收到 message 的值作为第一个参数。

过滤器可以串联:

{{ message | filterA | filterB }}
1

在这个例子中,filterA 被定义为接收单个参数的过滤器函数,表达式 message 的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB,将 filterA 的结果传递到 filterB 中。

过滤器是 JavaScript 函数,因此可以接收参数:

{{ message | filterA('arg1', arg2) }}
1

这里,filterA 被定义为接收三个参数的过滤器函数。其中 message 的值作为第一个参数,普通字符串 'arg1' 作为第二个参数,表达式 arg2 的值作为第三个参数。

# 3. 小结

通过用法回顾可以知道,过滤器有两种使用方式,分别是在双花括号插值中和在 v-bind 表达式中。无论是哪种使用方式,它的使用形式都是表达式 | 过滤器1 | 过滤器2 | ...

并且,我们知道了过滤器的定义也有两种方式,分别是在组件选项内定义和使用全局APIVue.filter定义全局过滤器。在组件选项内定义的过滤器称为本地过滤器,它只能用于当前组件中。使用Vue.filter定义的过滤器称为全局过滤器,它可以用在任意组件中。

另外,我们还知道了过滤器不仅可以单个使用,还可以多个串联一起使用。当多个过滤器串联一起使用的时候,前一个过滤器的输出是后一个过滤器的输入,通过将多种不同的过滤器进行组合使用来将文本处理成最终需要的格式。

最后,官方文档还说了所谓过滤器本质上就是一个JS函数,所以我们在使用过滤器的时候还可以给过滤器传入参数,过滤器接收的第一个参数永远是表达式的值,或者是前一个过滤器处理后的结果,后续其余的参数可以被用于过滤器内部的过滤规则中。

了解了过滤器的用法之后,那么接下来我们就对其内部原理一探究竟。