摘要:上一篇文章我們寫到從入口文件一步步找到的構(gòu)造函數(shù),現(xiàn)在我們要去看看實例化經(jīng)歷的過程的構(gòu)造函數(shù)我們知道的構(gòu)造函數(shù)在中不明白的可以去看上一篇文章源碼學習筆記一。
上一篇文章我們寫到從入口文件一步步找到Vue的構(gòu)造函數(shù),現(xiàn)在我們要去看看Vue實例化經(jīng)歷的過程Vue的構(gòu)造函數(shù)
我們知道Vue的構(gòu)造函數(shù)在src/core/instance/index.js中,不明白的可以去看上一篇文章 Vue源碼學習筆記一。那我們關(guān)注一下Vue的構(gòu)造函數(shù)的內(nèi)容:
// src/core/instance/index.js import { initMixin } from "./init" // Vue的構(gòu)造函數(shù) function Vue (options) { //... 驗證環(huán)境 this._init(options) } // 在Vue原型上綁定實例方法 initMixin(Vue) // init stateMixin(Vue) // $set $delete $watch eventsMixin(Vue) // $on $once $off $emit lifecycleMixin(Vue) // _update $forceUpdate $destroy renderMixin(Vue) // $nextTick _render添加Vue屬性和方法
這邊我們可以看到Vue的構(gòu)造函數(shù)中執(zhí)行了init方法,從下方得知init是在srccoreinstanceinit.js中導出的initMixin函數(shù)中定義的
initMixinvm即this ,同時為實例添加一個唯一的uid, vm._isVue = true 監(jiān)聽對象變化時用于過濾vm,因為Vue的實例是不需要監(jiān)聽變化的。
// src/core/instance/init.js Vue.prototype._init = function (options?: Object) { const vm: Component = this // 當前實例添加了一個唯一的uid vm._uid = uid++ // ... // 監(jiān)聽對象變化時用于過濾vm vm._isVue = true //... }
參數(shù)處理,根據(jù)我們的小栗子,我們的options處理直接進入了else,然后對參數(shù)進行合并,這里是對vue extend的參數(shù)需要進行合并處理,我們這里resolveConstructorOptions 返回的即是constructor.options本身
生命周期相關(guān)變量初始化 initLifecycle(vm)
// srccoreinstancelifecycle.js // 為組件掛載相應屬性,并初始化 vm.$parent = parent vm.$root = parent ? parent.$root : vm vm.$children = [] vm.$refs = {} vm._watcher = null vm._inactive = null vm._directInactive = false vm._isMounted = false vm._isDestroyed = false vm._isBeingDestroyed = false
4.vm 事件監(jiān)聽初始化 initEvents()
// src/core/instance/events.js export function initEvents (vm: Component) { // 創(chuàng)建事件對象,用于存儲事件 vm._events = Object.create(null) // 系統(tǒng)事件標識位 vm._hasHookEvent = false // init parent attached events npm // 將父組件模板中注冊的事件放到當前組件實例的listeners const listeners = vm.$options._parentListeners if (listeners) { updateComponentListeners(vm, listeners) } }
initEvents(vm) initRender(vm) callHook(vm, "beforeCreate") initInjections(vm) // vm狀態(tài)初始化,prop/data/computed/method/watch都在這里初始化完成,vue實例create的關(guān)鍵 initState(vm) initProvide(vm) callHook(vm, "created")stateMixin
Vue實例方法--數(shù)據(jù),該文件對應的是Vue的數(shù)據(jù)的處理,首先對$data進行掛載,然后設(shè)置數(shù)據(jù)$set、刪除數(shù)據(jù)$delete、觀測數(shù)據(jù)$watch方法掛載
// stateMixin(Vue) src/core/instance/state.js export function stateMixin (Vue: ClasseventsMixin) { // data const dataDef = {} dataDef.get = function () { return this._data } // prop const propsDef = {} propsDef.get = function () { return this._props } // ... // 定義$data & prop屬性 Object.defineProperty(Vue.prototype, "$data", dataDef) Object.defineProperty(Vue.prototype, "$props", propsDef) // 原型鏈添加函數(shù)set 和 delete Vue.prototype.$set = set Vue.prototype.$delete = del // 原型鏈添加函數(shù)$watch Vue.prototype.$watch = function (){ // ... } }
Vue實例方法--事件,該文件主要掛載Vue實例方法的事件,監(jiān)聽事件on once、移除事件off、觸發(fā)事件emit的掛載
// eventsMixin(Vue) src/core/instance/events.js export function eventsMixin (Vue: ClasslifecycleMixin) { Vue.prototype.$on = function (event: string, fn: Function): Component { // ... } Vue.prototype.$once = function (event: string, fn: Function): Component { // ... } Vue.prototype.$off = function (event?: string, fn?: Function): Component { // ... } Vue.prototype.$emit = function (event: string): Component { // ... } }
Vue實例方法--生命周期,,該文件主要掛載Vue實例方法中的生命周期方法,重新渲染$forceUpdate()、銷毀實例$destroy()
// lifecycleMixin(Vue) src/core/instance/lifecycle.js Vue.prototype._mount = function(){} Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {} Vue.prototype._updateFromParent = function(){} Vue.prototype.$forceUpdate = function () {} Vue.prototype.$destroy = function () {}renderMixin
文件主要掛載Vue實例方法中的dom更新回調(diào)$nextTick及一些其他的render函數(shù),后續(xù)我們再的深挖一下
// renderMixin(Vue) src/core/instance/render.js Vue.prototype.$nextTick = function (fn: Function) {} Vue.prototype._render = function (): VNode {} Vue.prototype._s = _toString Vue.prototype._v = createTextVNode Vue.prototype._n = toNumber Vue.prototype._e = createEmptyVNode Vue.prototype._q = looseEqual Vue.prototype._i = looseIndexOf Vue.prototype._m = function(){} Vue.prototype._o = function(){} Vue.prototype._f = function resolveFilter (id) {} Vue.prototype._l = function(){} Vue.prototype._t = function(){} Vue.prototype._b = function(){} Vue.prototype._k = function(){}全局API
上面部分,我們對Vue的構(gòu)造函數(shù),在src/core/instance/index.js文件中的作用進行了大體的了解,當然這并沒有結(jié)束,依據(jù)我們Vue源碼學習筆記一中提到的,我們追溯到上一級src/core/index.js
// src/core/index.js 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) // 為vue原型定義屬性 isServer 判斷是否為服務端渲染 Object.defineProperty(Vue.prototype, "$isServer", { get: isServerRendering }) // 為vue原型定義屬性 ssrContext Object.defineProperty(Vue.prototype, "$ssrContext", { get () { /* istanbul ignore next */ return this.$vnode && this.$vnode.ssrContext } }) Object.defineProperty(Vue, "FunctionalRenderContext", { value: FunctionalRenderContext }) Vue.version = "__VERSION__" export default VueinitGlobalAPI(Vue)
在Vue 構(gòu)造函數(shù)上掛載靜態(tài)屬性和方法即全局API
// src/core/global-api/index.js export function initGlobalAPI(Vue: GlobalAPI) { const configDef = {} configDef.get = () => config // ... Object.defineProperty(Vue, "config", configDef) Vue.util = { // Vue.util warn, extend, mergeOptions, defineReactive } Vue.set = set Vue.delete = del Vue.nextTick = nextTick Vue.options = Object.create(null) ASSET_TYPES.forEach(type => { Vue.options[type + "s"] = Object.create(null) }) Vue.options._base = Vue extend(Vue.options.components, builtInComponents) initUse(Vue) // Vue.use initMixin(Vue) // Vue.mixin initExtend(Vue) // Vue.extend initAssetRegisters(Vue) // Vue.component Vue.directive Vue.filter }內(nèi)置組件&命令
在追溯到上一級,在文件src/platforms/web/runtime/index.js,該文件注冊了一些 Vue內(nèi)置的組件:包裹動態(tài)組件KeepAlive、元素過渡效果Transition、多個元素過渡TransitionGroup
// src/platforms/web/runtime/index.js 執(zhí)行后 // 安裝平臺特定的utils Vue.config.isUnknownElement = isUnknownElement Vue.config.isReservedTag = isReservedTag Vue.config.getTagNamespace = getTagNamespace Vue.config.mustUseProp = mustUseProp // 安裝平臺特定的 指令 和 組件 Vue.options = { components: { KeepAlive, Transition, TransitionGroup }, directives: { model, show }, filters: {}, _base: Vue } Vue.prototype.__patch__ Vue.prototype.$mountcompiler編譯器添加
再上一級為src/platforms/web/entry-runtime-with-compiler.js,該文件對原來的Vue.prototype.$mount進行覆蓋定義,并且在Vue上掛載了 compile。給Vue的 $mount 方法添加 compiler 編譯器,支持 template。
// src/platforms/web/entry-runtime-with-compiler.js const mount = Vue.prototype.$mount // ... Vue.prototype.$mount = function (){ //... 覆蓋 Vue.prototype.$mount } // ... //在 Vue 上掛載 compile //compileToFunctions 函數(shù)的作用,就是將模板 template 編譯為render函數(shù)。 Vue.compile = compileToFunctions總結(jié)
至此的話我們從宏觀上過了一下從我們一層層找到vue到一層層往外看到對Vue的添加屬性方法等,我們有了一個整體的概念
src/core/instance/index.js vue的構(gòu)造函數(shù),添加Vue屬性和方法
src/core/index.js 全局API的掛載
src/platforms/web/runtime/index.js 主要是添加web平臺特有的配置、組件和指令
web/entry-runtime-with-compiler.js 給Vue的 $mount 方法添加 compiler 編譯器,支持 template
scripts/config.js 編譯入口文件
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/99898.html
摘要:其中執(zhí)行命令是我們當前所關(guān)注的,對于項目的文件結(jié)構(gòu),我們需要去找到項目的啟動的入口文件,接下來我們?nèi)ヒ徊揭徊降恼业椒治雒钍且粋€模塊打包器。 打算開始學習vue的源碼開始,我開始 serach 關(guān)鍵詞:vue 源碼,可是發(fā)現(xiàn)很多都不是我想要看到的東西,所以打算記錄下來,學習的記錄和日后分享。我在想這個文章的名字時,手把手系列?十分鐘系列?小白到大佬系列?都不是,只是單純的學習筆記 文件...
摘要:一個基于全家桶開發(fā)的仿知乎日報單頁應用項目地址源碼地址項目在線地址在線地址模式下推薦使用移動端模式瀏覽去觀看如果覺得做得還不錯或者項目源碼對您有幫助希望您小抬右手到右上角點一個您的支持是作者長期更新維護的動力項目起源從二月份開始學習學習了 Vue-News 一個基于vue全家桶開發(fā)的仿知乎日報單頁應用 項目github地址:源碼地址 項目在線地址:在線地址 (PC模式下推薦使用chro...
摘要:很多小伙伴練手都會去仿寫豆瓣電影或者網(wǎng)易云音樂,所以,這回干脆把兩個集合起來,具體長什么樣,請各位看預覽或下面圖片啦。怎么折騰法呢比如豆瓣部分我使用了,網(wǎng)易云部分則沒有,網(wǎng)易的組件則是自己造的輪子,當然在實際開發(fā)中肯定不會這么搞啦。。 很多小伙伴練手都會去仿寫豆瓣電影或者網(wǎng)易云音樂,所以,這回干脆把兩個集合起來,具體長什么樣,請各位看預覽或下面圖片啦。 目的: 做這個項目最主要的目的是...
摘要:介一回聊狀態(tài)模式,官方描述允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為。有限狀態(tài)機有限狀態(tài)機是一個非常有用的模型,可以模擬世界上大部分事物。這個是官方說法,簡單說,她有三個特征,狀態(tài)總數(shù)是有限的。,任一時刻,只處在一種狀態(tài)之中。 本回內(nèi)容介紹 上一回聊了聊組合模式(Composite),用組合模式模擬了個圖片庫,聊了遞歸。介一回聊狀態(tài)模式(State),官方描述允許一個對象在其內(nèi)部狀態(tài)改...
寫文章不容易,點個贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【Vue原理】Compile - 源碼版 之 Parse 主要流程 本文難度較繁瑣,需要耐心觀看,如果你對 compile 源碼暫時...
閱讀 1427·2023-04-25 23:42
閱讀 3140·2021-11-19 09:40
閱讀 3623·2021-10-19 11:44
閱讀 3850·2021-10-14 09:42
閱讀 2038·2021-10-13 09:39
閱讀 3960·2021-09-22 15:43
閱讀 746·2019-08-30 15:54
閱讀 1529·2019-08-26 13:32