手把手教你從零寫一個簡單的 VUE


本系列是一個教程,下面貼下目錄~
1.手把手教你從零寫一個簡單的 VUE
2.手把手教你從零寫一個簡單的 VUE--模板篇

今天給大家帶來的是實現一個簡單的類似 VUE 一樣的前端框架,VUE 框架現在應該算是非常主流的前端數據驅動框架,今天我們來從零開始寫一個非常簡單的 VUE 框架,主要是讓大家知道最核心的 vue 部分是怎么運轉起來的。包括數據綁定,模板處理,以及頁面渲染,數據驅動視圖等幾個部分,代碼在文章末尾給出來,下面我們開始~

VUE 是怎么運轉起來的

在正式動手之前,我們先來了解下 vue 是怎么運轉起來的,vue 從核心來說,是一個通過數據去驅動頁面渲染的框架,也就是說通過改變數據的狀態,可以控制頁面中渲染的邏輯,比如展示數據,切換樣式,這些的核心都是通過對數據改變的監聽,從而將數據發生改變的對應的視圖進行更新渲染,這是整個框架的核心運行機制。因此我們制作的簡單 vue 框架,主要是圍繞着怎么監聽,怎么渲染,怎么更新這個流程去做的,旨在讓大家知道 vue 怎么跑起來的,其余的 vue 組件,指令,插件等內容將在后面的文章中寫出。

設計

首先我們要知道我們要做一個簡單數據驅動視圖前端框架,它包括以下幾個部分:

  1. 能夠編譯簡單的模板
  2. 能夠監聽數據變化
  3. 數據變化的時候,能夠關聯對應的視圖並同步的更新視圖

根據上面列舉的需求,我們需要程序抽象以下幾個部分:

  1. 存儲數據的$data,用於保存數據,渲染視圖
  2. 與每個模板對應的Node對象,對象包含對應模板的渲染函數,還有渲染函數需要使用的數據集合
  3. 對數據進行監聽關聯的Watcher類,用於關聯數據和對應的模板,監聽數據變化

開始編碼

首先介紹下項目用的工具及框架,項目使用rollup進行項目模塊化構建,使用ES6進行編碼。下面開始正式編碼。
首先我給框架起了個簡單的名字,叫QV,這個對象會暴露到全局中,進行實例化,實例化代碼如下:
圖片描述
在實例化的時候傳給了對象 eltemplatedata等數據,其中el是模板在頁面的掛載點,template 是獲取模板的選擇器,分別對應body<app></app>標簽和script標簽中的模板,data 是定義的數據對象。

數據處理

QV類的構造函數中,我們會對傳入的配置進行處理,首先我們會對數據進行格式化,使得其在被Watcher正常監控。格式化數據的代碼如下:
圖片描述
可以看到formatData方法在原來的data上面又掛載了一個_od_屬性,然后將原始數據進行格式化,每個數據分別包含value(數據值),linkNodes(被使用的節點值),mounted(是否已經被格式化過),通過對數據進行預處理,方便后面的數據監控綁定

模板節點處理

模板的能力是一個前端框架的重要組成部分,vue將模板轉化為AST(抽象語法樹),然后去解析其中的語法,比如{{}}v-for v-if等等,模板解析的總體思路如下:

  1. 將模板字符串通過正則表達式等方法進行切割,切割點為模板定義的關鍵字
  2. 將切割完的字符串進行分析,可以生成AST(抽象語法樹)或者是直接進行處理操作
  3. 將分析完的東西進行字符串拼接,通過new Function生成模板函數

本例子只做流程的說明,所以模板很簡單,只有賦值語法,如下:
圖片描述
可以看到模板中只有{{}}的賦值語法,插入變量為a、sdf、ccc的語法
那么這個是怎么進行解析的呢,代碼如下:
圖片描述
下面重點講一講這個函數,可以看到函數的開頭定義了一個正則表達式 /{{[ \t]*([\w\W]*?)[ \t]*}}/g,用於匹配和分割用{{}}界定的變量,通過 exec的運行,匹配出來的結果如下:
圖片描述
可以看到a,sdf,ccc都被匹配出來了,然后通過slice進行分割后重建,變成一段模板函數字符串,如下:
clipboard.png
然后再通過new Function將上面的字符串變成一個函數,方法如下
clipboard.png
其中的new Function("od",$t)中的od是這個函數的參數,可以在函數中使用
最后生成的模板函數如下:
clipboard.png
這樣子就完成了模板函數的開發,而且還將模板用的變量進行抽取,標記這個模板用到了哪些變量

監聽器

監聽器作為連接數據和視圖更新的紐帶,是vue的核心部分,vue是使用Object.defineProperty對數據進行處理后實現數據監聽的,本程序也是使用這個核心方法進行數據監聽的,核心代碼如下:
圖片描述
下面我具體說下這段代碼:
之前格式化數據的時候在原始數據里面添加了_od_字段,是用在數據監控時候的,Object.defineProperty可以設置get set屬性,分別在對應的數據被獲取或者被修改的時候會進行回調,因此如果直接操作原始數據,會導致監控程序發生死循環,因此通過_od_的拷貝數據進行操作,能夠避免這種情況,可以看到get函數會直接返回_od_里面對應屬性的value,而set函數我做了一個優化節流,對於連續修改數據只發生一次更新,將使用到這個數據的Node對象進行update操作

程序最核心的方法已經開發完成了,演示下結果,直接打開頁面,可以看到下面的視圖
clipboard.png
可以看到程序將數據a sdf ccc賦值給模板,然后替換頁面的app節點,渲染到頁面上
接下來我們通過實例直接修改data
qv.$data.a = "change data a"
可以看到頁面會更新成為
圖片描述
下面說下重新渲染的流程:

  1. 數據修改之后觸發了Object.definePropertyset方法,方法檢測到設置數據與原數據不同,回去獲取linkNodes屬性,里面包含了使用這個數據的Node節點,然后分別調用Node節點的update方法
  2. update方法被調用之后,Node會重新獲取data去生成dom元素,然后替換現有的模板元素,至此完成一次更新

結語

這篇文章的例子旨在跟大家說明Vue是怎么運作的,希望可以幫助到大家在日常使用的時候遇到一些坑,可以從根本原理上面去找原因,當然這個demo 離Vue還是非常不完整的,缺少了各種模板語法,指令,事件綁定,組件系統,只是把核心的流程展現出來,希望大家喜歡

最后附上源碼 點我點我,喜歡的話給個 star 唄~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM