日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

vue data 值如何渲染_Vue执行流程解析

發布時間:2024/10/14 vue 113 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue data 值如何渲染_Vue执行流程解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

相信絕大多數的前端小伙伴已記不清做了多少項目,寫了多少代碼了,每個人如同教科書般地寫著Vue代碼:

// 單文件組件中常見代碼 export default {data () {return {msg: 'click me'}},methods: {say () {this.msg = 'well done'}} }// 入口文件中的常見代碼 new Vue({el: '#app',router: router,render: h => h(App) })

一切都顯得那么自然。不過在百忙之中是否有小伙伴想過,一個小小的Vue實例怎么有這么大的能量,竟然可以構建出如此復雜的前端項目。那么Vue內部是如何運轉的呢,做了哪些事情呢,從今天開始跟著我一探究竟。

vue是可以運行在多平臺上的如瀏覽器,weex等,本文只分析vue在瀏覽器環境下的主線執行流程。

初始化

我們先看一下Vue的構造函數:

// Vue構造函數 function Vue (options) {if (process.env.NODE_ENV !== 'production' &&!(this instanceof Vue)) {warn('Vue is a constructor and should be called with the `new` keyword')}// 執行初始化邏輯this._init(options) }

從Vue的構造函數中可以看到,當我們執行new Vue()的時候,只執行了一個_init方法。_init會根據傳入的選項對vue進行初始化。props、data、生命周期,事件機制的初始化都是在此過程中完成的。

以data的初始化為例,vue會通過 Object.defineProperty 的方式將data的屬性定義到vue實例上。這也就解釋了為什么我們可以在vue中通過對 this.msg 進行賦值,可以修改data中屬性的值了。

以上對data的處理只是剛剛開始。為了能實現所謂的響應式或者數據驅動更新,vue又做了進一步的處理,具體做法是,創建一個observer對象,該對象與data綁定,通過 Object.defineProperty 將data中的所有的屬性轉換成getter/setter。當data中的屬性在vue實例中被訪問(會觸發getter),observer 對象就會把該屬性收集為watcher實例的依賴,之后當data中的屬性在vue實例中被改變(會觸發setter), observer 會通知依賴該屬性的 watcher 實例重新渲染頁面。

注:每個watcher都對應一個vue實例

以上處理流程串在一起,vue就實現了通過修改 this.msg 從而觸發頁面的自動更新。

最后借用vue官網上的一張示意圖幫助大家再理解下這個處理過程:

模板解析

通過上面的分析,我們已經知道當數據發生變化時,會觸發頁面的重新渲染。接下來我們分析下vue是如何進行渲染的。

首先,vue會把將我們編寫的HTML模板解析成一個AST描述對象,該對象是通過children和parent鏈接而成的樹形結構,完整地描述了HTML標簽的所有信息。

例如有如下HTML模板:

<div id="app"><p>{{msg}}</p> </div>

最終會解析成如下形式的AST對象:

{attrs: [{name: "id", value: ""app"", dynamic: undefined, start: 5, end: 13}],attrsList: [{name: "id", value: "app", start: 5, end: 13}],attrsMap: {id: "app"},children: [{attrsList: [],attrsMap: {},children: [],end: 33,parent: {type: 1, tag: "div", ...},plain: true,pre: undefined,rawAttrsMap:{},start: 19tag: "p",type: 1}],end: 263,parent: undefined,plain: false,rawAttrsMap:{id: {name: "id", value: "app", start: 5, end: 13}},start: 0tag: "div",type: 1 }

然后 vue 根據AST對象生成 render 函數,該函數的函數體大致如下:

with(this){return _c('div', {attrs:{"id":"app"}}, [_c('p', [_v(_s(msg))])]) }

也就是說,我們的模板最終在vue內部都是會以一個render函數的形式存在。

vue官網上對此也有提及,一般推薦大家使用template,el等方式來指定模板,此外還可以通過使用render來自定義個性化的編譯函數,不過vue內部最終都會解析成render函數。

先虛后實

我們得到render函數之后,vue并未直接渲染成DOM樹,而是先通過render函數得到一個vnode。實際上這一步是非常有必要的,我們都知道頻繁大量地操作DOM節點是極耗性能的。vue在渲染之前通過對vnode的比較,可以大大規避非必要的DOM操作。下面是一個vnode大致結構:

{tag: "div",children: [{tag: "p", ...}],data: {attrs: {id: "app"}}elm: DOM節點(div#app),parent: undefined,context: Vue實例,... }

最后,vue根據diff之后的結果,執行真正的dom節點的插入更新刪除等操作,同時觸發vue實例的生命周期鉤子函數。之后,vue要做的就是觀察數據的變化,進而決定是否重新渲染頁面了。

總結

以上就是vue在初始渲染過程中的主干流程,大體總結起來就是先對選項對象初始化,通過Object.defineProperty建立一套響應式系統,然后將模板解析成render函數,然后使用render函數生成vnode,在渲染前,對vnode進行diff操作,最后進行必要的渲染。

本文并未深入每個執行中的代碼細節,接下來會詳細對初始化、響應式實現原理、模板渲染、指令解析、vnode的diff等進行介紹,敬請期待。

推薦閱讀

  • 如何使用 splitChunks 精細控制代碼分割
  • 用了這么久的react/vue,你真的了解hooks嗎?

總結

以上是生活随笔為你收集整理的vue data 值如何渲染_Vue执行流程解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。