前言
主要用到了 Object.defineProperty
这个方法改变或添加对象的属性, 改变这个对象的属性时触发 set 方法。
Reflect.defineProperty
基本等同于 Object.defineProperty
。
更多详见: Object.defineProperty 。
Vue 响应式原理:https://cn.vuejs.org/v2/guide/reactivity.html
Reflect.defineProperty 和 Object.defineProperty 区别:
Object.defineProperty
返回一个对象,或者如果属性没有被成功定义,抛出一个TypeError
。 相比之下,Reflect.defineProperty
方法只返回一个Boolean
,来说明该属性是否被成功定义。- ES6 中将
Object
的一些明显属于语言内部的方法移植到了Reflect
对象上(当前某些方法会同时存在于Object
和Reflect
对象上),未来的新方法会只部署在Reflect
对象上。
上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>defineProperty 实现简单双向绑定</title>
</head>
<body>
<div>
<div style="width: 300px; margin: 50px auto;">
<input id="input" />
<button onclick="handleClear()">clear</button>
</div>
<div style="font-size: 24px; width: 300px; margin: 50px auto;">
<div id="div"></div>
</div>
</div>
<script>
const obj = {};
// 添加属性监听
function addPropertyKeyListener(object, propertKey, callback) {
let tempValue = object[propertKey];
// Reflect.defineProperty 基本等同于 Object.defineProperty
// return Reflect.defineProperty(object, propertKey, {
return Object.defineProperty(object, propertKey, {
get: () => {
return tempValue;
},
set: (value) => {
console.log("触发 defineProperty set 事件, value: " + value);
tempValue = value;
callback(value);
}
});
};
// 添加输入框监听事件
document.getElementById("input").addEventListener("input", e => {
console.log("触发 addEventListener 监听事件");
obj.message = e.target.value;
});
// 更新div值
function updateDivValue(value) {
document.getElementById("div").innerHTML = value;
};
// 注册
addPropertyKeyListener(obj, "message", updateDivValue);
// 清空
function handleClear() {
obj.message = "";
document.getElementById("input").value = "";
}
</script>
</body>
</html>