1. 程式人生 > 其它 >【vue高階】MVVM實現原理 第三篇 編譯模板Compile

【vue高階】MVVM實現原理 第三篇 編譯模板Compile

技術標籤:vuevue

【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) } }) }

重新整理瀏覽器,我們就能看到編譯成功,插值替換成了真正想要顯示的資料
在這裡插入圖片描述

但這時候,我們修改屬性值,會發現頁面並沒有隨著更新,這就要實現編譯和資料劫持搭配起來運用,作為下一篇的內容進行講解