用生命谱写代码的赞歌

0%

使用访问器属性实现双向数据绑定

从去年开始经常接触到各种框架的双向数据绑定,一直没深入研究其机制,今天我就使用 JS 的访问器属性实现自己的双向数据绑定。

ES5数据属性

数据属性有4个描述其行为的特性:

  1. [[Configurable]]:表示能否通过delete删除属性并重新定义属性,能否修改属性的特性…例如

    1
    2
    3
    4
    5
    var person = {}
    Object.defineProperty(person, "name", {
    writable: false,
    value: "Nick"
    })
  2. [[Enumerable]]:表示能否通过for-in循环返回属性

  3. [[Writable]]:表示能否修改属性值

  4. [[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) // 2

访问器属性实现双向数据绑定

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>