摘要:上一篇文章我們寫到從入口文件一步步找到的構造函數,現在我們要去看看實例化經歷的過程的構造函數我們知道的構造函數在中不明白的可以去看上一篇文章源碼學習筆記一。
上一篇文章我們寫到從入口文件一步步找到Vue的構造函數,現在我們要去看看Vue實例化經歷的過程Vue的構造函數
我們知道Vue的構造函數在src/core/instance/index.js中,不明白的可以去看上一篇文章 Vue源碼學習筆記一。那我們關注一下Vue的構造函數的內容:
// src/core/instance/index.js import { initMixin } from "./init" // Vue的構造函數 function Vue (options) { //... 驗證環境 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的構造函數中執行了init方法,從下方得知init是在srccoreinstanceinit.js中導出的initMixin函數中定義的
initMixinvm即this ,同時為實例添加一個唯一的uid, vm._isVue = true 監聽對象變化時用于過濾vm,因為Vue的實例是不需要監聽變化的。
// src/core/instance/init.js Vue.prototype._init = function (options?: Object) { const vm: Component = this // 當前實例添加了一個唯一的uid vm._uid = uid++ // ... // 監聽對象變化時用于過濾vm vm._isVue = true //... }
參數處理,根據我們的小栗子,我們的options處理直接進入了else,然后對參數進行合并,這里是對vue extend的參數需要進行合并處理,我們這里resolveConstructorOptions 返回的即是constructor.options本身
生命周期相關變量初始化 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 事件監聽初始化 initEvents()
// src/core/instance/events.js export function initEvents (vm: Component) { // 創建事件對象,用于存儲事件 vm._events = Object.create(null) // 系統事件標識位 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狀態初始化,prop/data/computed/method/watch都在這里初始化完成,vue實例create的關鍵 initState(vm) initProvide(vm) callHook(vm, "created")stateMixin
Vue實例方法--數據,該文件對應的是Vue的數據的處理,首先對$data進行掛載,然后設置數據$set、刪除數據$delete、觀測數據$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) // 原型鏈添加函數set 和 delete Vue.prototype.$set = set Vue.prototype.$delete = del // 原型鏈添加函數$watch Vue.prototype.$watch = function (){ // ... } }
Vue實例方法--事件,該文件主要掛載Vue實例方法的事件,監聽事件on once、移除事件off、觸發事件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更新回調$nextTick及一些其他的render函數,后續我們再的深挖一下
// 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的構造函數,在src/core/instance/index.js文件中的作用進行了大體的了解,當然這并沒有結束,依據我們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 構造函數上掛載靜態屬性和方法即全局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 }內置組件&命令
在追溯到上一級,在文件src/platforms/web/runtime/index.js,該文件注冊了一些 Vue內置的組件:包裹動態組件KeepAlive、元素過渡效果Transition、多個元素過渡TransitionGroup
// src/platforms/web/runtime/index.js 執行后 // 安裝平臺特定的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 函數的作用,就是將模板 template 編譯為render函數。 Vue.compile = compileToFunctions總結
至此的話我們從宏觀上過了一下從我們一層層找到vue到一層層往外看到對Vue的添加屬性方法等,我們有了一個整體的概念
src/core/instance/index.js vue的構造函數,添加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 編譯入口文件
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99898.html
摘要:其中執行命令是我們當前所關注的,對于項目的文件結構,我們需要去找到項目的啟動的入口文件,接下來我們去一步一步的找到分析命令是一個模塊打包器。 打算開始學習vue的源碼開始,我開始 serach 關鍵詞:vue 源碼,可是發現很多都不是我想要看到的東西,所以打算記錄下來,學習的記錄和日后分享。我在想這個文章的名字時,手把手系列?十分鐘系列?小白到大佬系列?都不是,只是單純的學習筆記 文件...
摘要:一個基于全家桶開發的仿知乎日報單頁應用項目地址源碼地址項目在線地址在線地址模式下推薦使用移動端模式瀏覽去觀看如果覺得做得還不錯或者項目源碼對您有幫助希望您小抬右手到右上角點一個您的支持是作者長期更新維護的動力項目起源從二月份開始學習學習了 Vue-News 一個基于vue全家桶開發的仿知乎日報單頁應用 項目github地址:源碼地址 項目在線地址:在線地址 (PC模式下推薦使用chro...
摘要:很多小伙伴練手都會去仿寫豆瓣電影或者網易云音樂,所以,這回干脆把兩個集合起來,具體長什么樣,請各位看預覽或下面圖片啦。怎么折騰法呢比如豆瓣部分我使用了,網易云部分則沒有,網易的組件則是自己造的輪子,當然在實際開發中肯定不會這么搞啦。。 很多小伙伴練手都會去仿寫豆瓣電影或者網易云音樂,所以,這回干脆把兩個集合起來,具體長什么樣,請各位看預覽或下面圖片啦。 目的: 做這個項目最主要的目的是...
摘要:介一回聊狀態模式,官方描述允許一個對象在其內部狀態改變時改變它的行為。有限狀態機有限狀態機是一個非常有用的模型,可以模擬世界上大部分事物。這個是官方說法,簡單說,她有三個特征,狀態總數是有限的。,任一時刻,只處在一種狀態之中。 本回內容介紹 上一回聊了聊組合模式(Composite),用組合模式模擬了個圖片庫,聊了遞歸。介一回聊狀態模式(State),官方描述允許一個對象在其內部狀態改...
寫文章不容易,點個贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Compile - 源碼版 之 Parse 主要流程 本文難度較繁瑣,需要耐心觀看,如果你對 compile 源碼暫時...
閱讀 1341·2023-04-25 23:42
閱讀 2808·2021-11-19 09:40
閱讀 3520·2021-10-19 11:44
閱讀 3529·2021-10-14 09:42
閱讀 1860·2021-10-13 09:39
閱讀 3821·2021-09-22 15:43
閱讀 665·2019-08-30 15:54
閱讀 1448·2019-08-26 13:32