vue2.0 通过ES5: Object.defineProperty
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>vue2.0 数据双向绑定</title> </head> <body> 姓名:<span id="spanName"></span> <br /> <input type="text" id="inpName" /> <script> /** * 通过ES5: Object.defineProperty * 数据改变,触发视图重新渲染。视图改变,触发数据改变。 */ let obj = { name: "", }; /** * 简单实现深克隆 * 接收改变后的值,避免死循环 */ let newObj = JSON.parse(JSON.stringify(obj)); // 监听 obj 中 name 值的改变 Object.defineProperty(obj, "name", { get() { return newObj.name; // 通过新的变量接收改变后的值,避免出现死循环的情况 }, set(val) { if (val === newObj.name) return; newObj.name = val; observer(); }, }); // 观察者 function observer() { spanName.innerHTML = obj.name; // 获取 obj值的时候会触发 get() 获取最新的值 inpName.value = obj.name; } // observer(); /** * 模拟修改数据 * 数据的更改影响视图 */ setTimeout(() => { obj.name = "测试"; }, 1000); /** * 监听 input 文本框的改变 * 视图的改变影响数据 * 相当于 v-model */ inpName.oninput = function () { obj.name = this.value; }; /** * 存在的问题: * 1.需要对原始数据进行克隆 * 2.需要分别给对象中每一个属性设置监听 */ </script> </body> </html>
vue3.0 通过ES6 Proxy 拦截器实现数据双向绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>vue3.0 实现数据的双向数据绑定</title> </head> <body> 姓名:<span id="spanName"></span> <br /> <input type="text" id="inpName" /> <script> /** * 通过ES6 Proxy 拦截器实现数据双向绑定 * 1.不需要克隆 * 2.不需要对对象的每个属性设置监听 */ let obj = {}; /** * 监听整个对象 * 不需要指定属性 * 把当前对象的所有属性都监听(截持)了 */ obj = new Proxy(obj, { get(target, prop) { // target 就是 obj return target[prop]; }, set(target, prop, value) { target[prop] = value; observer(); }, }); // 观察者 function observer() { spanName.innerHTML = obj.name; // 获取 obj值的时候会触发 get() 获取最新的值 inpName.value = obj.name; } /** * 模拟修改数据 * 数据的更改影响视图 */ setTimeout(() => { obj.name = "测试"; }, 1000); /** * 监听 input 文本框的改变 * 视图的改变影响数据 * 相当于 v-model */ inpName.oninput = function () { obj.name = this.value; }; </script> </body> </html>
.