0
点赞
收藏
分享

微信扫一扫

带着问题看源码——为何vue中filters访问不了vue实例?

像小强一样活着 2022-02-07 阅读 31

带着问题看源码——为何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。

举报

相关推荐

0 条评论