概述
Proxy对象是ES6的特性,有点类似于Proxy代理模式,Proxy用于创建一个对象的代理,实现拦截以及其他的自定义操作,也就是对该对象任何操作都必须要经过这层拦截。Vue2用到的拦截方式是Object.defineProperty,这种方式有很大的弊端,对对象某个属性进行操作时,这种方式监听不到。Vue3采取Proxy对对象进行拦截。这种拦截方式的好处是,对象只需要关注核心的逻辑,一些非核心逻辑由proxy来做,比如读取、设置某些属性前做一些操作,例如验证、访问控制等
proxy有两个主要部分组成,例如下面的代码:
var p = new Proxy(target,handler)
target代表代理对象,handler在结构上是一个对象,声明了被代理对象的一些操作,每次对p进行操作,都会触发handler的一些方法。
虚拟属性
本身被拦截的代理对象没有相应的属性
比如下面person对象没有fullName属性
let person = {
firstName:"白",
lastName:"小纯"
}
var proxyedPerson = new Proxy(person,{
get:function(target,key){
if(key == 'fullName'){
// join() 方法将数组作为字符串返回,元素将有指定的分隔符分隔,磨人的分隔符是逗号
return [target.firstName,target.lastName].join(' ')
}
return target[key]
},
set(target,key,value){
if(key == 'fullName'){
var fullNameInfo = value.split(' ')
target.firstName = fullNameInfo[0]
target.lastName = fullNameInfo[1]
}else{
target[key] = value
}
}
})
私有变量
私有变量就是只能在内部使用的变量,在外部无法操作,比如函数的参数、局部变量、函数内部的其他函数等,这些在外部都是无法访问的。
在代理中,把以_开头的变量都认为是私有的
代码:
var api = {
_secret : 'xxx',
_otherSec : 'bbb',
version : 'v0.0.1'
}
api = new Proxy(api,{
get(target,key){
// 以_开头的变量都默认认为是私有的
if(key.startsWith('_')){
console.log('私有变量不能被访问')
return false
}
return target[key]
},
set(target,key,value){
if(key.startsWith('_')){
console.log('私有变量不能被修改')
return false
}
target[key] = value
}
})
拦截方法
拦截方式有13种,下面先举出2种最常用的
get
形式参数:target、key
作用:对被代理的对象进行读取的操作
代码:
get(target,key){
console.log(`${key}`被读取)
return target[key]
}
set
形式参数:target、key、value
作用:设置target的属性值
代码:
set(target,key,value){
console.log(`${key}被设置为${value}`)
target[key] = value;
}