Vue在2.X版本与3.X版本关于数据的双向绑定是不同的。
在2.X中使用的是Object.defineProperty;在3.X中使用的是ES6的Proxy。以下就两种原理作简单实现。
-
Vue2.X数据双向绑定实现:
<body> 输入:<span id="viewContent"></span> <p> <input type="text" id="modelContent"> </p> </body> <script> let viewContent = document.getElementById('viewContent'); let modelContent = document.getElementById('modelContent'); /* Vue2.X----> Object.defineProperty()实现数据双向绑定 * 缺点: * 1. 需要对原对象进行赋值一份 * 2. 对于每个属性都需要先进行定义,如果不定义,则无法监听数据的变动 * 3. 这也是为什么Vue中一些数据的方法不能直接使用以及对象的变动特殊处理的原因 */ let obj = {name: ''}; let newObj = JSON.parse(JSON.stringify(obj));//先复制一份 Object.defineProperty(obj, 'name', { get(){ // return obj.name; 不可以这样做,这样会造成死循环 return newObj.name; }, set(val){ if(newObj.name === val) return; // 如果两次值相同,直接返回 newObj.name = val; observer(); //观察者 } }) // 观察者 function observer() { viewContent.innerHTML = obj.name; modelContent.value = obj.name; } setTimeout(_ => { obj.name = "你好" }, 1000); // 数据Model绑定 modelContent.oninput = function(e) { let event = e || window.event; obj.name = e.target.value; } </script>
-
Vue3.X数据绑定Proxy实现:
-
<body> 输入:<span id="viewContent"></span> <p> <input type="text" id="modelContent"> </p> </body> <script> /* Vue3.X-------> 使用ES6中的Proxy来实现数据的双向绑定 * */ let obj = {}; obj = new Proxy(obj, { get(target, propKey){ return target[propKey]; }, set(target, propKey, value){ target[propKey] = value; observer(); } }); // 观察者 function observer() { viewContent.innerHTML = obj.name; modelContent.value = obj.name; } setTimeout(_ => { obj.name = "你好" }, 1000); // 数据Model绑定 modelContent.oninput = function(e) { let event = e || window.event; obj.name = e.target.value; } </script>
Vue2.X的实现相对Vue3.X数据双向绑定的缺点
从代码中,我们能很清除的发现,缺点主要如下:
-
需要对原对象进行复制一份;
-
对于每个属性都需要先进行定义,如果不定义,则无法监听数据的变动;
-
这也是为什么Vue中一些数据的方法不能直接使用以及对象的变动特殊处理的原因