【vue高级】MVVM实现原理 第一篇 Object.defineProperty
【vue高级】MVVM实现原理 第二篇 数据劫持Observe
【vue高级】MVVM实现原理 第三篇 编译模板Compile
我们已经有了数据,接下来就是要用数据替换掉html中的插值,以 {{}} 为例
先把数据写复杂一点点
data: {
a: { a: 1 },
b: 2,
},
页面结构也复杂一点点
<div id="app">
<p>{{a.a}}</p>
<p>{{b}}</p>
</div>
现在页面显示是这样
我们需要编译一下,编译文档内容,自然需要文档dom和vue实例
我们要把它拿到文档碎片中去操作
function Compile(el, vm) {
// el 表示替换的范围
vm.$el = document.querySelector(el)
let fragment = document.createDocumentFragment()
while (child = vm.$el.firstChild) { // 将app 中的内容移入到内存中
fragment.appendChild(child)
}
}
现在,我们再刷新浏览器,会发现,页面空了,是因为都拿到内存中去了,接下来我们把它塞回去
vm.$el.appendChild(fragment)
但不能原封不动的塞回去,得先匹配到插值进行替换后再塞回去,替换方法如下:
function replace(fragment) {
Array.from(fragment.childNodes).forEach(function (node) {
// 循环每一层
let text = node.textContent
let reg = /\{\{(.*)\}\}/
if (node.nodeType === 3 && reg.test(text)) {
let arr = RegExp.$1.split('.')
let val = vm
arr.forEach(function (k) {
val = val[k]
})
console.log(val);
node.textContent = text.replace(/\{\{(.*)\}\}/, val)
}
if (node.childNodes) {
replace(node)
}
})
}
刷新浏览器,我们就能看到编译成功,插值替换成了真正想要显示的数据
但这时候,我们修改属性值,会发现页面并没有随着更新,这就要实现编译和数据劫持搭配起来运用,作为下一篇的内容进行讲解