摘要:的構造函數將自動運行啟動函數。我在閱讀源碼的過程中,發現源碼余行,而和模板編譯相關的代碼,則約有行左右。這個是創建的方法,作為第一個參數傳入。最后會返回一個節點。這個時候將賦值為這個節點,掛載完成
mount, 意思為掛載。可以理解為將vue實例(邏輯應用),掛靠在某個dom元素(載體)上的一個過程。
一、創建Vue實例時的渲染過程上一篇文章我們講到, 在創建一個vue實例的時候(var vm = new Vue(options))。Vue的構造函數將自動運行 this._init(啟動函數)。啟動函數的最后一步為initRender(vm),
// Vue.prototype._init ... initLifecycle(vm); initEvents(vm); callHook(vm, "beforeCreate"); initState(vm); callHook(vm, "created"); initRender(vm);
initRender中調用vm.$mount(vm.$options.el),將實例掛載到dom上,至此啟動函數完成。
//initRender ... if (vm.$options.el) { vm.$mount(vm.$options.el); }
可以看出,vm.$mount為vue渲染的主要函數
二、Vue的渲染機制上圖,展示的是獨立構建時的一個渲染流程圖
模板字符串
//模板字符串{{message}}
render函數
//render函數 function anonymous() { with(this){return _h("div",{attrs:{"id":"app"}},[" "+_s(message)+" "])} }
vnode
真實dom節點($el)
獨立構建 與 運行時構建我們先看一下官方文檔 獨立構建和運行時構建
這兩個概念,我在初學的時候是一頭霧水。現在對照著渲染的流程圖,我們可以知道
獨立構建:包含模板編譯器
渲染過程: html字符串 → render函數 → vnode → 真實dom節點
運行時構建: 不包含模板編譯器
渲染過程: render函數 → vnode → 真實dom節點
運行時構建通過砍掉模板編譯器,讓整個包少了30%(官方數據)。我在閱讀源碼的過程中,發現vue源碼7000余行,而和模板編譯相關的代碼,則約有1000行左右。看起來確實是輕便了。這是在鼓勵我們多用render函數嗎?
三、$mount函數上面我們說到,運行時構建的包,會比獨立構建少一個模板編譯器。在$mount函數上也不同
運行時構建的 $mount函數
而獨立構建的 $mount函數,會先用一個臨時變量mount保存上面的$mount方法
var mount = Vue$2.prototype.$mount; //此處mount即為運行時版的 $mount
然后重寫$mount函數,這時,調用$mount就會包括模板編譯功能了
var mount = Vue$2.prototype.$mount; Vue$2.prototype.$mount = function (el, hydrating) { ...省略代碼(里面為模板編譯器入口)... return mount.call(this, el, hydrating) };
我們可以看到,不管獨立構建還是運行時構建,都會調用 vm._mount方法我們來看看源碼
Vue.prototype._mount = function(el, hydrating) { ...一些防止運行時的包,卻用了template的報錯代碼... callHook(vm, "beforeMount"); vm._watcher = new Watcher(vm, function () { vm._update(vm._render(), hydrating); }, noop); hydrating = false; if (vm.$vnode == null) { vm._isMounted = true; callHook(vm, "mounted"); } return vm }
使用過的vue的人,都會很敏銳地發現, 在調用beforeMount生命周期,和mounted生命周期中間的關鍵代碼為
鑒于大牛已經講過很多次這里的數據監聽了,我們只講其中渲染部分
vm._update(vm._render(), hydrating);
vm._render函數返回一個vnode作為 vm._update的參數。 hydrating是與服務器渲染(SSR)相關的,瀏覽器端可以不用管。
vm._render (將render函數轉化成vnode)
最核心代碼為
var render = vm.$options.render try{ vnode = render.call(vm._renderProxy, vm.$createElement); }catch{ ... }
此處,使用call方法, 將this指向 vm.renderProxy js功底差的同學要去補補知識了。
vm.renderProxy是個代理,代理vm,主要用來報錯,如果render函數上使用了vm上沒有的屬性或方法,就會報錯。
vm.$createElement 這個是創建vnode的方法,作為第一個參數傳入。
render函數
這里的h即是, vm.$createElement ,便是在vm._render這個階段被傳入。
vm._update (將vnode生成真實dom節點)
最關鍵一句話為
vm.$el = vm.__patch__(prevVnode, vnode);
vm.__patch__也是個大家伙,我之后會再去研究。
里面的方法,將新舊vnode使用 diff算法進行比對,找出要替換的地方,這樣更新dom的性能會有較大優化。
最后會返回一個dom節點。
這個時候將vm.$el 賦值為這個dom節點,掛載完成!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83077.html
摘要:源碼版本構造器實例選項讓我們用一段展示一下這三個概念其中的構造器實例實例名可以任意取,這里我們便于理解保持和文檔一致選項即為傳入構造器里的配置選項。其實構造器上也綁了不少好用的方法。 源碼版本:2.0.5 構造器、實例、選項 讓我們用一段demo展示一下這三個概念: //HTML {{ message }} //JS var vm = new Vue({ el: #app,...
摘要:代碼初始化部分一個的時候做了什么當我們一個時,實際上執行了的構造函數,這個構造函數內部掛載了很多方法,可以在我的上一篇文章中看到。合并構造函數上掛載的與當前傳入的非生產環境,包裝實例本身,在后期渲染時候,做一些校驗提示輸出。 概述 在使用vue的時候,data,computed,watch是一些經常用到的概念,那么他們是怎么實現的呢,讓我們從一個小demo開始分析一下它的流程。 dem...
摘要:結論父子組件生命周期鉤子的執行順序遵循從外到內,然后再從內到外,不管嵌套幾層深,也遵循這個規律。組件化的設計思路大抵相同,中父子組件生命周期鉤子執行順序,具體沒做探究,但是值得一提的是父組件的也是晚于子組件執行的。 如今前端框架都流行組件化,頁面元素都可以使用組件進行高度概括,那么處理組件之間的關系就如同處理頁面架構一樣重要。正確理解組件之間的關系,才能讓代碼按照我們與預料方式工作。最...
摘要:依舊采取傳統的開發技術棧進行開發,同時在終端的運行體驗不輸。首先來看下前端開發框架目前與構成了三大最流行的前端開發框架,具有組件化以及三大特性,還學習的,引入了狀態管理模塊。 摘要: WEEX依舊采取傳統的web開發技術棧進行開發,同時app在終端的運行體驗不輸native app。其同時解決了開發效率、發版速度以及用戶體驗三個核心問題。那么WEEX是如何實現的?目前WEEX已經完全開...
摘要:在前端頁面中,把用純對象表示,負責顯示,兩者做到了最大限度的分離。的顯示與否和的布爾值有關,還是只關注數據的變化。兩個組件的布爾值通過兩個臨近的按鈕控制,初始值和的結果都是。組件的聲明在組件上,則完全沒有進入生命周期。 開始前說一說 吐槽 首先, 文章有謬誤的地方, 請評論, 我會進行驗證修改。謝謝。 vue真是個好東西,但vue的中文文檔還有很大的改進空間,有點大雜燴的意思,對于怎么...
閱讀 2671·2021-11-25 09:43
閱讀 2579·2021-11-22 09:34
閱讀 2823·2021-11-12 10:34
閱讀 1431·2021-10-20 13:46
閱讀 2300·2019-08-30 13:21
閱讀 929·2019-08-30 11:21
閱讀 483·2019-08-30 11:20
閱讀 2186·2019-08-29 17:20