首先先介绍一下proxy
proxy是ES6提供的一个构造函数。是用于过滤拦截和改写的。当外界对对象进行访问时,都必须通过这一层拦截,可以被过滤或者改写。
举一个例子:
var proxy = new Proxy({},{
get:function(target,property){
return 35
}
})
proxy.time //35
proxy.name //35
首先对象中的get方法是读取对象中的内容,无论读取什么都返回35
我创造了一个实例,传入目标对象是一个空对象(针对于上图例子所示),第二个参数是拦截它的函数,这里是无论访问这个对象任何属性都会范返回35。
那么我们在举一个完整的例子。
var person = {
name:'张三'
}
var proxy = new Proxy(preson, {
get:function(target,property){
if(property in target) {
return target[property]
}else {
throw new ReferenceError("Property \"" + property + "\" dose not exist.");
}
}
});
proxy.name // '张三'
proxy.age // 抛出错误
上面这一段代码就是。当我访问对象中存在的属性,可以正常返回我,但是当我访问对象中没有的属性就会返回一个空。也充分说明,这个proxy构造函数的作用。
说一下proxy的语法:
let p = new Proxy(target, handler);
参数:
target
用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler
一个对象,其属性是当执行一个操作时定义代理的行为的函数。
基础例子
let handler = {
get: function(target, name){
return name in target ? target[name] : 37;
}
};
let p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37
同样这个hander参数可以通过对象的get属性或者set属性对对象进行验证或者是过滤。
讲真我查了很多资料始终不太理解hander这个意思。根据MDN上的例子,也在这里说明一下。附上链接。
proxyMDN链接
如果我写的不明白,可以直接看网址哦。
然后我们看回VUE的源码:
路径:src/core/instance/proxy.js
节选部分内容关于proxy
initProxy = function initProxy (vm) {
if (hasProxy) {
// determine which proxy handler to use
const options = vm.$options
const handlers = options.render && options.render._withStripped
? getHandler
: hasHandler
vm._renderProxy = new Proxy(vm, handlers)
} else {
vm._renderProxy = vm
}
}
行吧我研究半天,真没太理解它这段是啥意思,为什么要用options判断,又是render属性什么的。大概情况就是某种状态下用proxy,另外一种状态就是vue实例。
这里附上部分hasHandle的代码,可以说明,他是判断了部分信息。如果发生错误,当我们在开发环境下会有报错提示。warnReservedPrefix,warnNonPresent 则是提示信息的函数
const hasHandler = {
has (target, key) {
const has = key in target
const isAllowed = allowedGlobals(key) ||
(typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data))
if (!has && !isAllowed) {
if (key in target.$data) warnReservedPrefix(target, key)
else warnNonPresent(target, key)
}
return has || !isAllowed
}
}
文字提示报错方法 warnReservedPrefix :
const warnReservedPrefix = (target, key) => {
warn(
`Property "${key}" must be accessed with "$data.${key}" because ` +
'properties starting with "$" or "_" are not proxied in the Vue instance to ' +
'prevent conflicts with Vue internals. ' +
'See: https://vuejs.org/v2/api/#data',
target
)
}
文字提示报错方法 warnNonPresent :
const warnNonPresent = (target, key) => {
warn(
`Property or method "${key}" is not defined on the instance but ` +
'referenced during render. Make sure that this property is reactive, ' +
'either in the data option, or for class-based components, by ' +
'initializing the property. ' +
'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.',
target
)
}
大概就是这个样子,因为看到很多信息说vue3.0更新了proxy,但是一直没有深入了解过这个到底是啥。看来es6还是很重要的~虽然平时用的比较多的都是数组或者对象的方法。文章中有借鉴es6入门这本书。等回青岛仔细看看之前买的vue源码的书关于proxy中内容会回来补充的。希望这篇文章可以帮到你们呢,虽然我也不是很厉害的大神呀。
另外的补充: Proxy 可以完美监听到任何方式的数据改变,唯一缺陷可能就是浏览器的兼容性不好。