Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<button onclick="changeMyValue()">点击我</button>
</div>
<script>
let obj ={};
let num = 1;
Object.defineProperty(obj,"key",{
get : function(){
console.log("get",num);
return num;
},
set : function(newValue){
console.log("set",newValue)
num = newValue;
},
enumerable : true,
configurable : true
});
console.log(obj.key);
function changeMyValue(){
console.log("click me")
obj.key++;
console.log("result",obj.key);
}
</script>
</body>
</html>
get在访问对象属性时被调用,set在修改对象属性时调用
权威网站讲解
vue在进行数据双向绑定时的原理,就是通过Object.defineProperty(),在get方法中将劫持所有的属性添加到监听队列中,在数据发生变化时,在set方法中调用notify通知dom元素进行更新
- 改良一下
function DefineReactive(obj, key, value) { // value == obj[key]
// 劫持并监听所有的属性
Object.defineProperty(obj, key, {
enumerable: true,// 是否可变
configurable: false, // 是否可更改编写
get() {
// 初始化,添加观察对象入依赖收集器中,相当于订阅-观察者模式的事件池...
console.log("get",value);
return value
},
set: (newVal) => {
// 1.对更改的数据也添加监听...
// 2.数据变化通知DOM变化...
console.log("set",newVal);
if (newVal !== value) {
value = newVal;
}
}
})
}
let dataObj = {
num:0
};
DefineReactive(dataObj,"num",0);
console.log(dataObj.num);
// 点击事件
function changeMyValue(){
console.log("click me");
dataObj.num++;
console.log("result",dataObj.num);
}