前言
偶然之间打开了vue官网,在首页发现了官方出了一个源码解析的文档分支,就学习了一波,并打算动手敲敲,写个文章加深印象
proxy
遇事不决,先copy一下官网的前两句
proxy修改的是程序默认形为,就形同于在编程语言层面上做修改,属于元编程(meta programming)
元编程(英语:Metaprogramming,又译超编程,是指某类计算机程序的编写,这类计算机程序编写或者操纵其它程序(或者自身)作为它们的数据,或者在运行时完成部分本应在编译时完成的工作
proxy参数
- target
targer是需要proxy代理的目标对象,可以是任何类型的对象 - handler
handler是一个通常以函数作为属性的对象,其中函数是用来定义代理对象的行为。
handler对象的方法
其中handler对象的方法有不少,主要就学习了当前接触比较多的get和set方法
- get方法主要有三个参数,obj、p、receiver。
obj是目标对象,p是读取的属性,receiver通常是proxy本身。
const obj = {
name: 'xiaochen',
};
const proxy = new Proxy(obj, {
get: (obj, p, receiver) => {
// 模板对象
console.log(obj);
// 读取的属性
console.log(p);
// proxy本身
console.log(receiver);
},
});
console.log(procy.name);
- set方法主要有四个参数,obj、p、newValue、receiver
obj是目标对象,p是读取的属性,newValue是新设置的值,receiver通常是proxy本身。 set方法是返回值,代表设置新的值成功,如果返回false会抛异常
const obj = {
name: 'xiaochen',
};
const proxy = new Proxy(obj, {
set: (obj, p, newValue, receiver) => {
console.log(obj);
console.log(p);
console.log(newValue);
console.log(receiver);
return true;
},
});
procy.name = '我是新的值';
proxy实现双向绑定
<template>
<div class="form">
<input type="text" @input="changeValue" />
<div id="text"></div>
</div>
</template>
<script setup>
let obj = {
name: '我自有一剑开天门',
};
let proxy = new Proxy(obj, {
set: (target, p, newValue, receiver) => {
console.log(target);
console.log(p);
console.log(newValue);
console.log(receiver);
updateDom(newValue);
return true;
},
});
// 更新Dom
function updateDom(objData: { name: string }) {
document.getElementById('text').innerHTML = objData;
}
function changeValue(e) {
proxy.name = e.target.value;
}
<script>
Object.defineProperty
Object.defineProperty() 方法可以用来修改对象的属性或者是新增属性并返回此对象。
该方法主要用三个参数,分别为obj、prop、descriptor
# obj为目标对象
# prop为需要操作(新增或者修改)的属性
# descriptor为属性描述符(属性描述符又可以分为数据描述符、存取描述符)
Object.defineProperty(obj, prop, descriptor)
属性描述符
configurable 属性
configurable 特性表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改,默认为false。
enumerable
configurable用来控制对象属性是否可以被枚举(我本来想写遍历,但是网上都是用枚举描述),所以就是用枚举,默认为false。
value
value 该属性的值,默认为undefined
writable
writable 上面的value值是否可修改,当该属性为false时,value值不可修改,默认为false
get
get 方法在对象属性被读取时调用,如果加了return,那么return的值会作为返回值,默认为undefined。
set
set 方法在对象属性被修改时调用,该方法接收一个参数,该参数为新的值,默认为undefined。
数据描述符和存取描述符
其中configurable、enumerable、value、writable被称为数据描述符,而get方法和set方法被称为存取描述符,当使用get和set方法时,不能使用value和writable,不然会抛异常。
Object.defineProperty实现双向绑定
<template>
<div class="form">
<input type="text" @input="changeValue" />
<div id="text"></div>
</div>
</template>
<script setup>
let obj = {
name: '我是一个有趣的对象',
};
Object.defineProperty(obj, 'name', {
enumerable: true,
get() {
console.log('糟糕,我被劫持了,救我');
return '我被读取了';
},
set(val) {
// 我在同步更新Dom
console.log(`我是新的值${val}`);
updateDom(val);
},
});
// 更新Dom
function updateDom(objData: { name: string }) {
document.getElementById('text').innerHTML = objData;
}
function changeValue(e) {
obj.name = e.target.value;
console.log(obj.name);
}
<script>
总结
这样看来vue2实现双向绑定时,大致是get方法收集依赖,set方法更新视图,其中configurable和enumerable都为true。