Proxy

150 阅读2分钟

概述

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;
}