摘要:主要大綱從方法看全局配置尋根問祖的構(gòu)造函數(shù)的出生地先來一段最常見的代碼上面已經(jīng)創(chuàng)建了一個(gè)應(yīng)用程序從上面很容易就看出來是一個(gè)構(gòu)造器,是用這個(gè)構(gòu)造器構(gòu)造出來的實(shí)例化對象,實(shí)例化的時(shí)候傳入了參數(shù),參數(shù)中包括和上述延伸了個(gè)問題構(gòu)造器是什么模樣可以
主要大綱:
從initGlobalAPI方法看Vue.config全局配置
尋根問祖-Vue的構(gòu)造函數(shù)的出生地
先來一段最常見的vue代碼demo
{{ message }}// js var vm = new Vue({ el: "#app", data: { message: ‘hello vue" } })
上面已經(jīng)創(chuàng)建了一個(gè)vue應(yīng)用程序;從上面很容易就看出來 Vue是一個(gè)構(gòu)造器,vm是用這個(gè)構(gòu)造器構(gòu)造出來的實(shí)例化對象,實(shí)例化的時(shí)候傳入了參數(shù),參數(shù)中包括el和data
上述延伸了3個(gè)問題:
Vue 構(gòu)造器是什么模樣?
Vm可以使用的方法,即vue的開放API都在源碼里面怎么實(shí)現(xiàn)的?
我們傳入構(gòu)造方法內(nèi)的參數(shù)發(fā)生了什么
這些問題是我們解鎖vue源碼的最開始的步驟,所以我們不妨通過vue源碼的入口開始尋找這些源碼的實(shí)現(xiàn)
在源碼的src/platforms/web下面放著不同版本的構(gòu)建entry文件,這些文件中導(dǎo)出export的Vue,都是從src/core/instance/index這個(gè)文件import過來的,
我們先看下入口文件能帶給我們什么答案:
// src/core/instance/index import Vue from "./instance/index" import { initGlobalAPI } from "./global-api/index" import { isServerRendering } from "core/util/env" import { FunctionalRenderContext } from "core/vdom/create-functional-component" initGlobalAPI(Vue)
這個(gè)入口文件做了3件事:
引用了 ./instance/index, 暴露了vue的來源,即構(gòu)造器
調(diào)用initGlobalAPI方法,將vue傳進(jìn)去, 給vue拓展了全局靜態(tài)方法
將vue暴露出去
這個(gè)入口文件的意義,是在暴露vue之前,給vue通過initGlobalAPI方法給vue拓展了全局靜態(tài)方法,對應(yīng)Vue的外部API是 Vue.config,包含了Vue的全局配置,
Vue.config.silent // 日志與警告 Vue.config.errorHandler // 這個(gè)處理函數(shù)被調(diào)用的時(shí)候,可以獲取錯(cuò)誤信息和Vue實(shí)例 Vue.config.devtools // 配置是否允許 vue-devtools 檢查代碼 …..從initGlobalAPI方法看Vue.config全局配置
initGlobalAPI方法定義了configDef對象,它的getter方法會(huì)的屬性值是config,setter方法給出警告不允許修改。最后在vue上添加了config屬性,屬性描述返回configDef對象
export function initGlobalAPI (Vue: GlobalAPI) { // config const configDef = {} configDef.get = () => config if (process.env.NODE_ENV !== "production") { configDef.set = () => { warn( "Do not replace the Vue.config object, set individual fields instead." ) } } Object.defineProperty(Vue, "config", configDef) // 添加config屬性
除此之外,還定義了util屬性,但是并沒有暴露到外面,也并不建議外部去使用
尋根問祖-Vue的構(gòu)造函數(shù)的出生地了解了構(gòu)造函數(shù),也就知道了new vue()的時(shí)候發(fā)生了什么
下面這段代碼就是Vue的構(gòu)造方法,我們可以直觀的看出vue構(gòu)造器是使用ES5的Function去實(shí)現(xiàn)類,是因?yàn)榭梢酝ㄟ^prototype往vue原型上拓展很多方法,把這些方法拆分到不同的文件/模塊下,這樣更有利于代碼的維護(hù),與協(xié)同開發(fā)
比如在這個(gè)文件中,可以看到把Vue當(dāng)作一個(gè)參數(shù)傳進(jìn)下面的**Mixin方法中,這些方法都是通過接收vue,在它的prototype上面定義一些功能的;
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’) // vue必須是new vue()的實(shí)例化對象 } console.log("options", options) this._init(options) // 調(diào)用內(nèi)部_init方法 } initMixin(Vue) // 在created生命周期函數(shù)之前的操作 stateMixin(Vue) // 利用 definedProperty 進(jìn)行靜態(tài)數(shù)據(jù)的訂閱發(fā)布 eventsMixin(Vue) // 實(shí)例事件流的注入, 利用的是訂閱發(fā)布模式的事件流構(gòu)造 lifecycleMixin(Vue) // renderMixin(Vue) // 實(shí)現(xiàn) _render 渲染虛擬dom export default Vue
這個(gè)構(gòu)造函數(shù)的最核心點(diǎn),就是this._init(options)
在此處打斷點(diǎn),可以看到參數(shù)options傳進(jìn)來的就是外面我們實(shí)例化時(shí)傳入的參數(shù)el 和 data
new Vue({ el: "#app", data: { message: ‘hello vue" } })
這個(gè)_init方法出自initMixin 函數(shù)
看完這個(gè)函數(shù),我們梳理出整個(gè)初始化階段源碼的幾個(gè)重要的節(jié)點(diǎn)
初始化options參數(shù)進(jìn)行合并配置
初始化生命周期
初始化時(shí)間系統(tǒng)
初始化state,包括data、props、 computed、watcher
export function initMixin (Vue: Class
console.log("Vue", Vue) Vue.prototype._init = function (options?: Object) { const vm: Component = this // a uid 實(shí)例化的uid遞增1 vm._uid = uid++ let startTag, endTag /* istanbul ignore if */
...
// 用_isVue來標(biāo)識(shí)當(dāng)前的實(shí)例是個(gè)Vue實(shí)例,這樣做是為了后續(xù)被observed vm._isVue = true // 合并配置options,并判斷是否是內(nèi)部Component的options的初始化 if (options && options._isComponent) { // 內(nèi)部 initInternalComponent(vm, options) } else { // 非內(nèi)部 vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) } // 在render中將this指向vm._renderProxy if (process.env.NODE_ENV !== "production") { initProxy(vm) } else { vm._renderProxy = vm } // expose real self vm._self = vm // 初始化生命周期 initLifecycle(vm) // 初始化事件注冊 initEvents(vm) // 初始化渲染 initRender(vm) // 觸發(fā)回掉函數(shù)中的beforeCreate鉤子函數(shù) callHook(vm, "beforeCreate") initInjections(vm) // resolve injections before data/props // 初始化vm的狀態(tài),包括data、props、computed、watcher等 initState(vm) initProvide(vm) // resolve provide after data/props // vm已經(jīng)創(chuàng)建好來,回掉created鉤子函數(shù) callHook(vm, "created’) /* istanbul ignore if */ … // 將實(shí)例進(jìn)行掛載 if (vm.$options.el) { vm.$mount(vm.$options.el) } }
}
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/109241.html
摘要:用造個(gè)組件輪子吧閏土大叔如果你掌握了的組件知識(shí),相關(guān)的指令事件,花點(diǎn)時(shí)間你也可以造出這么個(gè)入門級(jí)的小輪子。接下來,拋出造輪子實(shí)踐背后帶來的一些思考。以上三部分內(nèi)容構(gòu)成了的整個(gè)執(zhí)行過程。 showImg(https://segmentfault.com/img/bV1Tnu?w=754&h=500); 前言 首先,向大家說聲抱歉。由于之前的井底之蛙,誤認(rèn)為Vue.js還遠(yuǎn)沒有覆蓋到二三線...
摘要:構(gòu)造函數(shù)文件路徑初始化這里只拿對例子理解最關(guān)鍵的步驟分析。在最后,調(diào)用了對數(shù)據(jù)進(jìn)行。每個(gè)函數(shù)之后都會(huì)返回一個(gè)。就是去實(shí)例化指令,將指令和新建的元素在一起,然后將元素替換到中去。 下面的代碼會(huì)在頁面上輸出Hello World,但是在這個(gè)new Vue()到頁面渲染之間,到底發(fā)生了什么。這篇文章希望通過最簡單的例子,去了解Vue源碼過程。這里分析的源碼版本是Vue.version = 1...
摘要:寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺得排版難看,請點(diǎn)擊下面鏈接或者拉到下面關(guān)注公眾號(hào)也可以吧原理白話版從模板上使用到掛載到頁面 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于...
摘要:假如你通過閱讀源碼,掌握了對的實(shí)現(xiàn)原理,對生態(tài)系統(tǒng)有了充分的認(rèn)識(shí),那你會(huì)在面試環(huán)節(jié)游刃有余,達(dá)到晉級(jí)阿里的技術(shù)功底,從而提高個(gè)人競爭力,面試加分更容易拿。 前言 一年一度緊張刺激的高考開始了,與此同時(shí),我也沒閑著,奔走在各大公司的前端面試環(huán)節(jié),不斷積累著經(jīng)驗(yàn),一路升級(jí)打怪。 最近兩年,太原作為一個(gè)準(zhǔn)二線城市,各大互聯(lián)網(wǎng)公司的技術(shù)棧也在升級(jí)換代,假如你在太原面試前端崗位,而你的技術(shù)庫里若...
摘要:慢慢地,關(guān)于的原創(chuàng)學(xué)習(xí)文章已經(jīng)寫了多篇了會(huì)一直放出來,目前篇,因此做一個(gè)合集,獻(xiàn)給那些對新版本腳手架使用和背后設(shè)計(jì)感興趣的同學(xué),都是一步一步去看源碼,也給官方提了幾次,合進(jìn)去了幾個(gè)原創(chuàng)不易,歡迎大家互相轉(zhuǎn)發(fā),期望大家一起快速過度到版本目錄 慢慢地,關(guān)于 Vue CLI 3 的原創(chuàng)學(xué)習(xí)文章已經(jīng)寫了 20 多篇了(會(huì)一直放出來,目前 23 篇), 因此做一個(gè)合集,獻(xiàn)給那些對新版本腳手架使用...
閱讀 3573·2023-04-26 00:05
閱讀 959·2021-11-11 16:55
閱讀 3539·2021-09-26 09:46
閱讀 3525·2019-08-30 15:56
閱讀 919·2019-08-30 15:55
閱讀 2941·2019-08-30 15:53
閱讀 1954·2019-08-29 17:11
閱讀 822·2019-08-29 16:52