【vue高階】MVVM實現原理 第三篇 編譯模板Compile
阿新 • • 發佈:2021-02-05
【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)
}
})
}
重新整理瀏覽器,我們就能看到編譯成功,插值替換成了真正想要顯示的資料
但這時候,我們修改屬性值,會發現頁面並沒有隨著更新,這就要實現編譯和資料劫持搭配起來運用,作為下一篇的內容進行講解