Object.defineProperty(obj,property,descriptor)
对属性的读取、修改进行拦截(数据劫持)。
obj绑定属性的目标对象property绑定的属性名descriptor属性(配置)对象对新对象p进行数据劫持,当访问到name属性时,会执行get()方法,从而返回源对象person的name属性。当修改p的name属性时,会执行set()方法,此时源对象的person中name属性就会同步更改
// 设置源数据
const person = {
name: "玩偶姐姐",
age: 24,
hobby: ["抽烟", "喝酒", "打豆豆"],
};
const p = {};
Object.defineProperty(p, "name", {
// 属性值
// value: 12,
//控制属性是否可以枚举,默认值是false
// enumerable: true,
//控制属性是否可以被修改,默认值是false
// writable: true,
//控制属性是否可以被删除,默认值是false
configurable: true,
// 当有人读取p的name属性时执行
get() {
console.log("读取了person的name属性");
return person.name;
},
// 当有人修改p的name属性时执行
set(value) {
console.log("修改了person的name属性");
person.name = value;
},
});
注意:在给对象设置 get 和 set 存取数据时,就不能设置属性值 value 和可读性 wriable,两者不可共存,使用 get 和 set 作为替代对属性进行读和取,所以只需要设置一个允许删除即可
通过object.defineproperty()来实现一个简单的响应式demo
<div>请输入 : <input type="text" /></div>
<br />
<textarea cols="30" rows="10"></textarea>
<script>
const obj = {
demo: "",
};
const newObj = {};
Object.defineProperty(newObj, "demo", {
configurable: true,
get() {
console.log("读取到到了数据");
return obj.demo;
},
set(value) {
console.log(`我同步了新数据${value}`);
obj.demo = value;
document.querySelector("input").value = value;
document.querySelector("textarea").value = value;
},
});
document.querySelector("input").addEventListener("input", function () {
newObj.demo = this.value;
});
document.querySelector("textarea").addEventListener("input", function () {
newObj.demo = this.value;
});
</script>
Proxy
包装的目标对象
(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。handler以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p
的行为。通过proxy对person的代理,从而拦截对象的读取,修改删除属性操作,然后再通过p映射到person对象上面,从而达到响应数据
// 设置源数据
const person = {
name: "玩偶姐姐",
age: 24,
hobby: ["抽烟", "喝酒", "打豆豆"],
};
const p = new Proxy(person, {
//有人读取p的某个属性时调用
get(target, propName) {
console.log(`有人读取了p身上的${propName}属性`);
return Reflect.get(target, propName);
},
//有人修改p的某个属性、或给p追加某个属性时调用
set(target, propName, value) {
console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`);
Reflect.set(target, propName, value);
},
//有人删除p的某个属性时调用
deleteProperty(target, propName) {
console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`);
return Reflect.deleteProperty(target, propName);
},
});
当然,如果在不用reflect的情况下,也是可以实现数据响应的
// 设置源数据
const person = {
name: "玩偶姐姐",
age: 24,
hobby: ["抽烟", "喝酒", "打豆豆"],
};
const p = new Proxy(person, {
get(target, propName) {
console.log(`有人读取了p身上的${propName}属性`);
return target[propName];
},
set(target, propName, value) {
console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`);
return (target[propName] = value);
},
deleteProperty(target, propName) {
console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`);
return delete target[propName];
},
});
<div>请输入 : <input type="text" /></div>
<br />
<textarea cols="30" rows="10"></textarea>
<script>
const obj = {
demo: "",
};
const newObj = new Proxy(obj, {
// 有人读取p的某个属性时调用
get(target, propName) {
console.log(`有人读取了p身上的${propName}属性`);
return Reflect.get(target, propName);
},
//有人修改p的某个属性、或给p追加某个属性时调用
set(target, propName, value) {
console.log(`我同步了新数据${value}`);
Reflect.set(target, propName, value);
document.querySelector("input").value = value;
document.querySelector("textarea").value = value;
},
//有人删除p的某个属性时调用
deleteProperty(target, propName) {
return Reflect.deleteProperty(target, propName);
},
});
document.querySelector("input").addEventListener("input", function () {
newObj.demo = this.value;
});
document.querySelector("textarea").addEventListener("input", function () {
newObj.demo = this.value;
});
以上就是v2v3响应式方面本人总结的内容,至于v3方面的为什么proxy要搭配reflet使用比较好,相关内容较多,请各位自行查阅吧,如有出错,欢迎各位大佬指出,小弟必将虚心求教