vue中的双向数据绑定原理与常见操作技巧详解

2020-06-16 06:39:21易采站长站整理

3. 实现任务的思路

上面我们只是实现了一个简单的数据双向绑定,而我们真正希望实现的是下面这种方式:


<div id="app">
<input type="text" v-model="text">
{{ text }}
</div>

<script>
var vm = new Vue({
el: '#app',
data: {
text: 'hello world'
}
});
</script>

即和vue一样的方式来实现数据的双向绑定,那么我们可以把整个实现过程分为下面几步:

输入框以及文本节点与data中的数据绑定

输入框内容变化时,data中的数据同步变化。即view => model的变化。

data中的数据变化 时,文本节点的内容同步变化。即model => view的变化。

4.DocumentFragment

如果希望实现任务,我们还需要使用到DocumentFragment文档片段,可以把它看做一个容器,如下所示:


<div id="app">

</div>
<script>
var flag = document.createDocumentFragment(),
span = document.createElement('span'),
textNode = document.createTextNode('hello world');
span.appendChild(textNode);
flag.appendChild(span);
document.querySelector('#app').appendChild(flag)
</script>

使用文档片段的好处在于:在文档片段上进行操作DOM,而不会影响到真实的DOM,操作完成后,我们就可以添加到真实的DOM上,这样的效率比直接在正式DOM上修改要高很多。

vue在进行编译时,就是将挂载目标的所有子节点劫持到DocumentFragment中,经过一番处理之后,再将DocumentFragment整体返回插入挂载目标。

5.初始化数据绑定


function compile(node, vm) {
var reg = /{{(.*)}}/
// 如果节点是元素
if (node.nodeType === 1) {
var attr = node.attributes
for (var i = 0; i < attr.length; i++) {
if (attr[i].nodeName === 'v-model') {
var name = attr[i].nodeValue
node.value = vm.data[name] node.removeAttribute('v-model')
}

}
}

if (node.nodeType === 3) {
if (reg.test(node.nodeValue)) {
var name = RegExp.$1
name = name.trim()
node.nodeValue = vm.data[name] }
}
}

function nodeToFragment(node, vm) {
var flag = document.createDocumentFragment()
var child
while(child = node.firstChild) {
compile(child, vm)
flag.appendChild(child)
}
return flag
}

function Vue(options) {
this.data = options.data
var el = options.el
var dom = nodeToFragment(document.querySelector(el), this)

document.querySelector(el).appendChild(dom)
}

var vm = new Vue({