Vue
中为什么访问不了以$
和_
开头的属性?
背景:航班管家H5使用了Vue
进行新版开发,预订流程逻辑copy参考了野鹅国际机票小程序,小程序中使用__
开头的属性作为私有属性。
如题,在data
中定义的以_
开头的属性就不 work 了。我很想问一句:WTF?
官方解答
以 _ 或 $ 开头的属性 不会 被 Vue 实例代理,因为它们可能和 Vue 内置的属性、API 方法冲突。—— data
emm,奈斯!本次分享可以结束了。
然鹅,你想不想知道Vue
内部是如何屏蔽掉此类属性的呢?往下看↓
在继续之前,我们有必要先了解下Proxy
是个什么东西。
Proxy
Proxy
译为'代理器',在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截。
举个栗子:假设你要和韩梅梅相亲,但妹子岂是你想见就见的?就需要一个中间人——媒婆作为韩梅梅的代理人和你通信。这里的媒婆所谓的代理器了。
虽然这个概念早已有之,但直到ES6
才出现在javascript
中。Proxy
提供了一种机制,可以对外界的访问进行过滤和改写:
var proxy = new Proxy({}, {
get: function(target, property) {
return 35;
}
});
proxy.time // 35
proxy.name // 35
阮老师的ECMAScript 6 入门——proxy讲的很详细。
Vue 实现
当执行new Vue()
时,函数内部会执行_init()
方法,其中有这一段:
// src/core/instance/init.js
Vue.prototype._init = function (options?: Object) {
...
if (process.env.NODE_ENV !== 'production') {
initProxy(vm)
} else {
vm._renderProxy = vm
}
...
}
initProxy
来自src/core/instance/proxy.js
initProxy = function initProxy (vm) {
vm._renderProxy = new Proxy(vm, {
has (target, key) {
const has = key in target
const isAllowed = key.charAt(0) === '_'
return has || !isAllowed
}
})
}
proxy.js
中,has
方法用于拦截hasProperty
操作,用来判断对象是否有某个属性或方法。
结论
当在Vue
中访问对象的属性时,initProxy
函数会将那些以_
开头的属性给过滤掉。
另,has
拦截的是hasProperty
操作,而不是hasOwnProperty
。
再另,虽然for...in
循环也用到了in
运算符,但是has
拦截对for...in
循环不生效。
破菲特!
诶,等等,还有$
是怎么回事儿?
???