「 此次想要本身學着實現簡單版的vue,從而對vue有更加深刻的理解。 」
推薦一個好用的vscode插件,能夠本地快速啓動服務器,並運行html文件,且擁有熱加載功能:"live server"。html
首先,咱們都知道,當使用 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
這裏咱們分爲四個步驟來實現。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);
加載script前:插件
加載script後:
詳細的代碼請看個人 github
歡迎關注個人公衆號查看更多系列文章~