从去年开始经常接触到各种框架的双向数据绑定,一直没深入研究其机制,今天我就使用 JS 的访问器属性实现自己的双向数据绑定。
ES5数据属性
数据属性有4个描述其行为的特性:
[[Configurable]]:表示能否通过delete删除属性并重新定义属性,能否修改属性的特性…例如
1 2 3 4 5
| var person = {} Object.defineProperty(person, "name", { writable: false, value: "Nick" })
|
[[Enumerable]]:表示能否通过for-in循环返回属性
[[Writable]]:表示能否修改属性值
[[Value]]:包含这个属性的数据值,默认为undefined
访问器属性
访问器属性不包含数据值,包含一对getter和setter函数(不是必需的)。在读取访问器属性时会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时会调用setter函数并传入新值,这个函数负责决定如何处理数据。例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var book = { _year: 2017, edition: 1 } Obj.defineProperty(book, "year", { get: function() { return this._year }, set: function(newValue) { if (newValue > 2017) { this._year = newValue this.edition += newValue - 2017 } } })
book.year = 2018 alert(book.edition)
|
访问器属性实现双向数据绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <title>Document</title> </head>
<body> <input id="inputDom" type="text" style="width:100px;height:40px;border:1px solid red" name="" value=""> <div id="bandleDom">
</div> </body>
</html> <script> var obj = { _name: '' } document.querySelector('#inputDom').onkeyup = function (e) { var _ele = e.target var inputVal = _ele.value console.log(inputVal) obj.name = inputVal } for (key in obj) { console.log(key) } Object.defineProperty(obj, 'name', { get() { return this._name }, set(newVal) { this._name = newVal document.querySelector('#bandleDom').innerHTML = newVal } }) </script>
|