概述
Vue中双向绑定的原理是使用了Object.defineProperty进行绑定的。
我们先来看下官方给出的说法:
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data
选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty
把这些属性全部转为 getter/setter。Object.defineProperty
是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
看一下Vue源码对于双向绑定的初期实现:
1. Even You 的初期定义(2013-07初次提交)
2. 在源码基础上进行了注释,注释的内容是个人理解,仅供参考。
<!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的文档说明:
Object.defineProperty(obj, prop, descriptor)
obj
要在其上定义属性的对象。
prop
要定义或修改的属性的名称。
descriptor
将被定义或修改的属性描述符。
文档地址: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
基于Object.defineProperty实现一个类似的功能:
<!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 - (一) Vue中双向绑定的原理-Object.defineProperty所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复