使用defineProperty进行双向绑定的原理
<!DOCTYPE html> <html> <head> <title>defineProperty</title> </head> <body> name:<input type="text" id="name"> age:<input type="number" id="age"> <br /> <br /> name:<span id="namep"></span> <br /> age:<span id="agep"></span> <script type="text/javascript"> function Obj() { } Obj.prototype.data = { name: "mvvm", age: 18 } let dataObj = new Obj(); Object.keys(dataObj.data).forEach(key => { Object.defineProperty(dataObj, key, { get: function() { return dataObj[key]; }, set: function(newValue) { document.getElementById(`${key}p`).innerHTML = newValue; dataObj.data[key] = newValue; } }); }); document.getElementById("name").addEventListener('keyup', function(e) { dataObj["name"] = e.target.value; }); document.getElementById("age").addEventListener('keyup', function(e) { dataObj["age"] = e.target.value; }); </script> </body> </html>
<!DOCTYPE html> <html> <head> <title>KOA</title> </head> <body> <input type="text" k-value="value" id="input" /> <div k-text="value" id="el"></div> <script type="text/javascript"> /**基本思路是使用Object.defineProperty对数据对象做属性get和set的监听,当有数据读取和赋值操作时则调用节点的指令,这样使用最通用的=等号赋值就可以了。*/ var elems = [document.getElementById('el'), document.getElementById('input')]; var data = { value: "hello" }; var command = { text: function(str) { this.innerHTML = str; }, value: function(str) { this.setAttribute('value', str); } } let scan = function() { for (let i = 0, len = elems.length; i < len; i++) { let elem = elems[i]; elem.command = []; for (let j = 0, len1 = elem.attributes.length; j < len1; j++) { let attr = elem.attributes[j]; if (attr.nodeName.indexOf('k-') >= 0) { //调用属性指令 command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]); elem.command.push(attr.nodeName.slice(2)); } } } } let bValue; /** * 定义属性劫持 */ let defineGetAndSet = function(obj, propName) { try { Object.defineProperty(obj, propName, { get: function() { return bValue; }, set: function(newValue) { bValue = newValue; scan(); }, enumerable: true, configurable: true }); } catch (err) { console.log("browser not supported"); } } //初始化数据 scan(); defineGetAndSet(data, 'value'); if (document.addEventListener) { elems[1].addEventListener('keyup', function(e) { data.value = e.target.value; }, false); } else { elems[1].attachEvent('onkeyup', function(e) { data.value = e.target.value; }, false); } setTimeout(function(){ data.value = 'hello kruce'; }, 2000) </script> </body> </html>