Vue中双向绑定的原理是使用了Object.defineProperty进行绑定的。
我们先来看下官方给出的说法:
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data
选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty
把这些属性全部转为 getter/setter。Object.defineProperty
是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
看一下Vue源码对于双向绑定的初期实现:
1. Even You 的初期定义(2013-07初次提交)
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78<!DOCTYPE html> <html> <head> <title>ideal</title> <meta charset="utf-8"> </head> <body> <div id="test"> <p>{{msg}}</p> <p>{{msg}}</p> <p>{{msg}}</p> <p>{{what}}</p> <p>{{hey}}</p> </div> <script> // span元素上绑定的自定义属性 var bindingMark = 'data-element-binding'; function Element (id, initData) { var self = this, // 当前绑定的ID元素,div id = test. el = self.el = document.getElementById(id); // 需要绑定的span bindings = {} ;// the internal copy // 用于set的data data = self.data = {}; // the external interface // 将{{mes}}转变成 <span data-element-binding='mes'></span> content = el.innerHTML.replace(/{{(.*)}}/g, markToken); el.innerHTML = content; // 1.将页面上转换好的span移除额外样式,这是因为bindings已经绑定上对应的span了,没有那些样式也可以。 // bindings[variable].els = el.querySelectorAll('[' + bindingMark + '="' + variable + '"]'); for (var variable in bindings) { bind(variable); } // 2.触发Object.defineProperty的set,将值更改到span上。 if (initData) { for (var variable in initData) { data[variable] = initData[variable] } } // 修改span标签样式 function markToken (match, variable) { bindings[variable] = {}; return '<span ' + bindingMark + '="' + variable +'"></span>' } function bind (variable) { // 绑定span bindings[variable].els = el.querySelectorAll('[' + bindingMark + '="' + variable + '"]'); // 移除样式 [].forEach.call(bindings[variable].els, function (e) { e.removeAttribute(bindingMark) }); Object.defineProperty(data, variable, { set: function (newVal) { [].forEach.call(bindings[variable].els, function (e) { e.textContent = newVal; bindings[variable].value = newVal }) }, get: function () { return bindings[variable].value } }) } } new Element('test',{ msg: 'hello', hey: 'hey' }); </script> </body> </html>
看一下Object.defineProperty的文档说明:
复制代码
1Object.defineProperty(obj, prop, descriptor)
复制代码
1
2
3
4
5
6obj 要在其上定义属性的对象。 prop 要定义或修改的属性的名称。 descriptor 将被定义或修改的属性描述符。
文档地址: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
基于Object.defineProperty实现一个类似的功能:
复制代码
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
41
42<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Bindings</title> </head> <body> <span id="mes"></span> <span id="hello"></span> </body> </html> <script> let initData = { mes: 'mes', hello: 'hello' }; let spans = []; let data = {}; function bind(key){ Object.defineProperty(data ,key, { set: function (newValue) { spans[key].textContent = newValue; spans[key].value = newValue }, get: function () { return spans[key].value; } }); }; // 绑定span for (let dataKey in initData) { spans[dataKey] = document.getElementById(dataKey); bind(dataKey); } // 触发set for (let dataKey in initData) { data[dataKey] = initData[dataKey]; } </script>
最后
以上就是跳跃衬衫最近收集整理的关于Vue - (一) Vue中双向绑定的原理-Object.defineProperty的全部内容,更多相关Vue内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复