实现vue3的proxy响应式

86 阅读2分钟

Proxy响应式

前要

众所周知,vue3数据绑定都是通过proxy来完成的。在我们开始之前,先说说vue2的实现

vue2数据绑定

即是defineProperty,它是Object上的一个方法,简单看一下如何通过它来实现数据绑定吧。

// Object.defineProperty,该方法接收三个参数
// obj:添加新属性的对象
// property:要添加的属性
// descriptor:新属性的描述
var person = {
    name: "syh"
};
Object.defineProperty(person, "age", {
    value: 3,
    writable: true,
    configurable: true,
    enumerable: true
});
Object.defineProperty(person, "sex", {
    get: function () {
        return "男";
        console.log("get");
    },
    set: function (v) {
        console.log("set " + v);
    }
});
console.log(person,person.sex);
//{ name: 'syh', age: 3 } 男


可以看到,当我们读person.sex时触发getter,读到返回值。通过这种方式,可以达到代理数据的读和写的效果。

但是问题相比Proxy差得远,简单说一下

一次只能监听一个属性,那么想要代理这个对象,就需要遍历监听。对于新增的属性,需要手动的监听。

reflect

这也是一个很重要的对象,有很多静态方法,能够代替definedProperty效果又比他好。响应式的数据的读和写也是通过reflect完成的。绑定数据或者说响应式还是依靠proxy,reflect只是负责读和写

const person = {
  name: "syh",
  age: 18,
}

console.log(Reflect.get(person, 'age'));
Reflect.set(person, 'sex', "nan")
console.log(person);

// 18
// { name: 'syh', age: 18, sex: 'nan' }

可以看到通过reflect新增属性也都可以直接读取

Proxy

// Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义
//(如属性查找、赋值、枚举、函数调用等)。

// Proxy用于给源对象增设一层代理对象,任何对**代理对象**的操作为都会被Proxy拦截。
//也就是对源对象操作不会被拦截,写过vue3的应该都清楚

const person = {
    name: "syh",
    age: 18
}

// target:源对象
// handle:本次访问的属性
// receiver:代理对象  代理对象的是可传课不传的,如果传了,就类似call,
//将this指向了代理对象

const proxy = new Proxy(person, {
    get(target, handler, receiver) {
        console.log("get");
        return target[handler];
    },
    set(target, handler, newVal, receiver) {
        console.log("set");
        target[handler] = newVal
    }
})

console.log(proxy.age);
proxy.sex = "男"
console.log(proxy);

// get
// 18
// set
// { name: 'syh', age: 18, sex: '男' }

不难理解,就是一个简单的拦截的作用,但很明显,target[handler]这种方式很不优雅,也有缺点,所以就需要结合reflect

Proxy&Reflect

const origin = {
    name: '鲨鱼辣椒',
    age: 25,
    gender: '男'
}
const handler = {
    // 相当于 get(o, p, p){return Reflect.get(o, p, p)},这里是简写
    get: Reflect.get,
    set: Reflect.set,
    has: Reflect.has,
}

const proxy = new Proxy(origin, handler)

console.log(proxy.name) // 鲨鱼辣椒
console.log(proxy.age) // 25
proxy.age = 26
console.log(proxy.age) // 26
console.log('gender' in proxy) // true

这样一个Proxy数据绑定就完成了

总结

本次文章的没有什么难点,在于理解它们的作用和基本用法即可

结语

本次的文章到这里就结束啦!♥♥♥读者大大们认为写的不错的话点个赞再走哦 ♥♥♥

每天一个知识点,每天都在进步!♥♥