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

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

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

VUE 是怎麼運轉起來的

在正式動手以前,咱們先來了解下 vue 是怎麼運轉起來的,vue 從核心來講,是一個經過數據去驅動頁面渲染的框架,也就是說經過改變數據的狀態,能夠控制頁面中渲染的邏輯,好比展現數據,切換樣式,這些的核心都是經過對數據改變的監聽,從而將數據發生改變的對應的視圖進行更新渲染,這是整個框架的核心運行機制。所以咱們製做的簡單 vue 框架,主要是圍繞着怎麼監聽,怎麼渲染,怎麼更新這個流程去作的,旨在讓你們知道 vue 怎麼跑起來的,其他的 vue 組件,指令,插件等內容將在後面的文章中寫出。git

設計

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

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

根據上面列舉的需求,咱們須要程序抽象如下幾個部分:正則表達式

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

開始編碼

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

數據處理

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

模板節點處理

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

  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操做dom

程序最核心的方法已經開發完成了,演示下結果,直接打開頁面,能夠看到下面的視圖
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 唄~~

相關文章
相關標籤/搜索