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

本文深入探讨了在Vue中filters无法访问vue实例的原因,通过源码分析揭示了Vue如何处理filters以及with作用域的影响。在严格模式下,filters内部的this可能为undefined而非window,这源于resolveFilter函数的执行上下文。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

带着问题看源码——为何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 renderMixin (Vue) {
    // install runtime convenience helpers
    installRenderHelpers(Vue.prototype); // 将_s/_f等方法都挂载到vue的原型上
    // ....此处省略N行代码
}
 // 核心代码
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的作用呢,将给定的表达式添加到在评估语句时使用的作用域链上。上述作用相当与在执行with大括号内的代码时,访问_c/_v/_s/_f函数时会先在vue实例上找,如果找不到再向上找(作用域链)
执行解析:
虽然说_f挂载到了vue实例原型上,但是我们会发现_f函数并不是真正的过滤器函数,它只是一个获取过滤器的一个函数,_f(resolveFilter函数)函数会返回一个resolveAsset函数用于获取指定的过滤器函数,而resolveAsset函数并没有挂载到vue原型上,所以此时resolveAsset函数内的执行上下文(this)并不是vue实例,而是window,所以真正的过滤器函数内部的this并没有指向vue,而是指向window,所以我们在filters中访问不了vue实例

(2)问题2:为什么有时候访问到的this是undefined而不是window?
因为使用 use strict 严格模式,在严格模式下,所有函数自执行this指向将不再是window而是undefined。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值