一步一步的實現Vue(一)

此次想要本身學着實現簡單版的vue,從而對vue有更加深刻的理解。

   推薦一個好用的vscode插件,能夠本地快速啓動服務器,並運行html文件,且擁有熱加載功能:"live server"。html

0一、看看真正的Vue

首先,咱們都知道,當使用 new Vue 的時候,就能夠將 html 中的模板{{}}用 data 裏面的數據替換,以下:vue

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../node_modules/vue/dist/vue.js"></script>
</head>
<body>
  <article id="root">
    <section>{{name}}</section>
    <section>{{message}}</section>
  </article>

  <script> 
    const app = new Vue({
      el: '#root',
      data: {
        name: 'romeo',
        message: 'wants to be rich',
      }
    })
</script>
</body>
</html>

此時,vue 會找到 el 這個節點,(若是有 template 屬性,則會將此字符串模板編譯爲 render 函數),而後生成抽象語法樹(AST),而後用data替換對應的數據,建立虛擬DOM,生成真正的DOM,並最終掛載到文檔中。node

既然咱們要一步一步來,那麼先只看最基本的:拿到節點,進行編譯,將節點與數據結合,並替換節點。git

0二、數據與模板結合

這裏咱們分爲四個步驟來實現。github

1. 獲取節點服務器

const rootElement = document.querySelector('#root');
const generateRoot = rootElement.cloneNode(true); // 避免對節點自己直接修改

2. 聲明數據app

const data = {
  name: 'romeo',
  message: 'wants to be rich',
}

3. 將數據與模板結合,這裏的模板就是克隆的節點。須要深度遍歷這顆樹,方法有遞歸或者用棧保存遍歷的節點,這裏採用遞歸實現。函數

function compiler(template, data) {
  const childNodes = template.childNodes;
  for (const childNode of childNodes) {
    const type = childNode.nodeType;
    switch(type) {
      case 1: // 元素節點,遞歸
        compiler(childNode, data);
        break;
      case 3: // 文本節點, 判斷是否有mustache{{}}
        let txt = childNode.nodeValue;
        txt = txt.replace(regMustache, function(_, g) {
          // 此函數的第0個參數爲匹配到的內容,例如 {{name}}
          // 第n個參數爲第n組內容,例如 name
          return data[g.trim()];
        })
        childNode.nodeValue = txt;
        break;
      default: break;
    }
  }
}

compiler(generateRoot, data); // 調用函數

4. 替換節點spa

rootElement.parentElement.replaceChild(generateRoot, rootElement);

0三、效果

加載script前:插件

image.gif

加載script後:

image.gif

詳細的代碼請看個人 github

歡迎關注個人公衆號查看更多系列文章~
公衆號二維碼.png

相關文章
相關標籤/搜索