带着问题看源码——为何vue中filters访问不了vue实例?
前言:我们在vue项目中,经常会使用到filters过滤器,用来对数据进行二次处理,使用起来特别方便,但是有些业务场景,确让人特别头疼,需要在filters依赖到vue实例上的属性,或者是方法。但是使用的时候往往不尽人意,会报错。然后打印this发现竟然是undefined。这是为什么呢?索性我就去看一下vue处理filters时的源码。
提出问题:
(1). 问题1:为什么访问不了vue实例?
首先我们找到vue源码vue.js文件,全局搜索filters发现关联到 一个方法 resolveFilter
function installRenderHelpers (target) {
// 省略一部分代码
target._s = toString;
target._f = resolveFilter; // 核心代码
target._v = createTextVNode;
// 省略一部分代码
}
// 核心代码
function resolveFilter (id) {
return resolveAsset(this.$options, 'filters', id, true) || identity
}
我发现vue在调用filters时,并不是直接调用。而是通过 resolveFilter方法获取到指定的过滤器函数,然后再执行这个过滤器函数。
知道这个之后,我们还需要知道vue中在模板解析中会将过滤器解析成什么形式。通过翻阅资料发现在vue中filters会解析成如下:
(function() {
with(this) {
return _c('标签名',[
_v(_s(_f("过滤器函数名")('传入的参数')))
])
}
}
// _c 是渲染函数
// _v 通过 上述 installRenderHelpers函数我们能知道 是创建文本节点的方法
// _s 通过 上述 installRenderHelpers函数我们能知道 是将内容转换为string的方法
// _f 通过 上述 installRenderHelpers函数我们能知道 就是resolveFilter函数,用来返回一个过滤函数
我们发现这个执行渲染的过程是执行在with作用域内的,with的作用呢,就是在with大括号内的表达式都会将传入的表达式拼接到表达式前面。(上述作用相当与让_c/_v/_s/_f函数内的this指向vue实例)
但是我们会发现_f函数并不是真正的过滤器函数,它只是一个获取过滤器的一个函数,_f(resolveFilter函数)函数会返回一个过滤器函数,所以真正的过滤器函数内部的this并没有因为with而指向vue实例,而是指向window,所以我们在filters中访问不了vue实例
(2)问题2:为什么访问到的this是undefined而不是window?
因为vue源码中心在函数顶部使用 use strict 严格模式,在严格模式下,所有函数自执行this指向将不再是window而是undefined。