<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        Vue源碼學習之初始化模塊init.js解析

        來源:懂視網 責編:小采 時間:2020-11-27 22:26:18
        文檔

        Vue源碼學習之初始化模塊init.js解析

        Vue源碼學習之初始化模塊init.js解析:我們看到了VUE分了很多模塊(initMixin()stateMixin()eventsMixin()lifecycleMixin()renderMixin()),通過使用Mixin模式,都是使用了JavaScript原型繼承的原理,在Vue的原型上面增加屬性和方法。我們繼續跟著this._init(options)走,這
        推薦度:
        導讀Vue源碼學習之初始化模塊init.js解析:我們看到了VUE分了很多模塊(initMixin()stateMixin()eventsMixin()lifecycleMixin()renderMixin()),通過使用Mixin模式,都是使用了JavaScript原型繼承的原理,在Vue的原型上面增加屬性和方法。我們繼續跟著this._init(options)走,這

        我們看到了VUE分了很多模塊(initMixin()stateMixin()eventsMixin()lifecycleMixin()renderMixin()),通過使用Mixin模式,都是使用了JavaScript原型繼承的原理,在Vue的原型上面增加屬性和方法。我們繼續跟著this._init(options)走,這個一點擊進去就知道了是進入了init.js文件是在initMixin函數里面給Vue原型添加的_init方法。首先來從宏觀看看這個init文件,可以看出主要是導出了兩個函數:initMixin和resolveConstructorOptions,具體作用我們一步步來討論。咋的一看這個文件,可能有些童鞋會看不明白函數參數括號里面寫的是什么鬼,這個其實是應用了flow的類型檢查,具體flow的使用這里就不介紹了,有興趣的請移步:https://flow.org/en/

        我們現在來看第一個函數initMixin,Vue實例在初始化的時候就調用了這個函數,

        let uid = 0
        
        export function initMixin (Vue: Class<Component>) {
         Vue.prototype._init = function (options?: Object) {
         const vm: Component = this
         // a uid
         vm._uid = uid++
        
         let startTag, endTag
         /* istanbul ignore if */ 【**注:istanbul 是代碼覆蓋率檢測工具,此注釋為代碼測試用**】
         if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
         startTag = `vue-perf-init:${vm._uid}`
         endTag = `vue-perf-end:${vm._uid}`
         mark(startTag)
         }
        
         // a flag to avoid this being observed
         vm._isVue = true
         // merge options
         if (options && options._isComponent) {
         // optimize internal component instantiation
         // since dynamic options merging is pretty slow, and none of the
         // internal component options needs special treatment.
         initInternalComponent(vm, options)
         } else {
         vm.$options = mergeOptions(
         resolveConstructorOptions(vm.constructor),
         options || {},
         vm
         )
         }
         /* istanbul ignore else */
         if (process.env.NODE_ENV !== 'production') {
         initProxy(vm)
         } else {
         vm._renderProxy = vm
         }
         // expose real self
         vm._self = vm
         initLifecycle(vm)
         initEvents(vm)
         initRender(vm)
         callHook(vm, 'beforeCreate')
         initInjections(vm) // resolve injections before data/props
         initState(vm)
         initProvide(vm) // resolve provide after data/props
         callHook(vm, 'created')
        
         /* istanbul ignore if */
         if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
         vm._name = formatComponentName(vm, false)
         mark(endTag)
         measure(`${vm._name} init`, startTag, endTag)
         }
        
         if (vm.$options.el) {
         vm.$mount(vm.$options.el)
         }
         }
        }
        
        

        我們本著宏觀簡化原則,這個函數里面前面有三個if判斷工作我們可以先不細化討論,大致第一個是用performance做性能監測,第二個合并option,第三個是做代理攔截,是ES6新特性,可參考阮一峰大神關于proxy的介紹【http://es6.ruanyifeng.com/#docs/proxy】。那么就進入了初始化函數主要點:

        initLifecycle(vm) //生命周期變量初始化
        initEvents(vm) //事件監聽初始化
        initRender(vm) //初始化渲染
        callHook(vm, 'beforeCreate') //回調鉤子beforeCreate
        initInjections(vm) //初始化注入
        initState(vm) // prop/data/computed/method/watch狀態初始化
        initProvide(vm) // resolve provide after data/props
        callHook(vm, 'created') //回調鉤子created
        /* istanbul ignore if */
        if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
         vm._name = formatComponentName(vm, false)
         mark(endTag)
         measure(`${vm._name} init`, startTag, endTag)
        }
        
        if (vm.$options.el) {
         vm.$mount(vm.$options.el)
        }
        
        

        這里來一個插曲start

        V2.1.8及以前的版本】這里比較方便理解在生命周期created之后再做render,那么在created之前就無法獲取DOM。這也是在有些源碼解析文章里面很容易見到的分析,也是正確的

        initLifecycle(vm)
        initEvents(vm)
        callHook(vm, 'beforeCreate')
        initState(vm)
        callHook(vm, 'created')
        initRender(vm) 

        v2.1.9及以后的版本】但到這里一開始就懵逼了很久render提到beforeCreate之前去了,那豈不是DOM在beforeCreate之前就能獲取到了?顯然不對了,請注意render雖然提前了,但是后面多了一個if這個if里面才獲取DOM的關鍵,這個if在2.1.8版本之前是在render函數里面的,在2.1.9之后被提出來,然后render函數提前了,至于為何提前暫未了解,此處只是踩了一個看其他源碼解析不同版本帶來的坑!

        initLifecycle(vm)
        initEvents(vm)
        initRender(vm)
        callHook(vm, 'beforeCreate')
        initState(vm)
        callHook(vm, 'created')
        if (vm.$options.el) {
         vm.$mount(vm.$options.el)
        }
        

        插曲end,繼續

        1.initLifecycle

        function initLifecycle (vm: Component) {
         const options = vm.$options
        
         // locate first non-abstract parent
         let parent = options.parent //我理解為父實例或者父組件
         if (parent && !options.abstract) { //例子中沒有parent,斷點代碼的時候自動跳過
         while (parent.$options.abstract && parent.$parent) {
         parent = parent.$parent
         }
         parent.$children.push(vm)
         }
        
         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
        }
        
        

        這個函數主要是有父實例的情況下處理vm.$parent和vm.$children這倆個實例屬性,我此處沒有就跳過,其他的就是新增了一些實例屬性

        2.initEvents

        function initEvents (vm: Component) {
         vm._events = Object.create(null)
         vm._hasHookEvent = false
         // init parent attached events
         const listeners = vm.$options._parentListeners
         if (listeners) {
         updateComponentListeners(vm, listeners)
         }
        }
        

        又新增兩個屬性,后面那個if條件里面是有父組件的事件時初始化,估計就是props和events父子組件通信的事件內容。

        3.initRender

        function initRender (vm: Component) {
         vm._vnode = null // the root of the child tree
         vm._staticTrees = null
         const parentVnode = vm.$vnode = vm.$options._parentVnode
         const renderContext = parentVnode && parentVnode.context
         vm.$slots = resolveSlots(vm.$options._renderChildren, renderContext)
         vm.$scopedSlots = emptyObject 
         vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false) 
         vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)
         const parentData = parentVnode && parentVnode.data 
         /* istanbul ignore else */
         if (process.env.NODE_ENV !== 'production') {
         defineReactive(vm, '$attrs', parentData && parentData.attrs, () => {
         !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm)
         }, true)
         defineReactive(vm, '$listeners', vm.$options._parentListeners, () => {
         !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm)
         }, true)
         } else {
         defineReactive(vm, '$attrs', parentData && parentData.attrs, null, true)
         defineReactive(vm, '$listeners', vm.$options._parentListeners, null, true)
         }
        }
        

        此函數也是初始化了節點屬性信息,綁定createElement函數到實例【并未掛載】,接下來調用beforeCreate回調鉤子;——TODO1:后續專題分析VUE渲染邏輯

        4.initInjections

        function initInjections (vm: Component) {
         const result = resolveInject(vm.$options.inject, vm)
         if (result) {
         observerState.shouldConvert = false
         Object.keys(result).forEach(key => {
         /* istanbul ignore else */
         if (process.env.NODE_ENV !== 'production') {
         defineReactive(vm, key, result[key], () => {
         warn(
         `Avoid mutating an injected value directly since the changes will be ` +
         `overwritten whenever the provided component re-renders. ` +
         `injection being mutated: "${key}"`,
         vm
         )
         })
         } else {
         defineReactive(vm, key, result[key])
         }
         })
         observerState.shouldConvert = true
         }
        }
        

        此函數也是當有inject屬性時做處理,源碼例子無inject斷點跑暫時跳過

        5.initState

        function initState (vm: Component) {
         vm._watchers = []
         const opts = vm.$options
         if (opts.props) initProps(vm, opts.props)
         if (opts.methods) initMethods(vm, opts.methods)
         if (opts.data) {
         initData(vm)
         } else {
         observe(vm._data = {}, true /* asRootData */)
         }
         if (opts.computed) initComputed(vm, opts.computed)
         if (opts.watch && opts.watch !== nativeWatch) {
         initWatch(vm, opts.watch)
         }
        }
        

        可以看出此處是對options傳入的props/methods/data/computed/watch屬性做初始化————TODO2:分析每個屬性的初始化

        6.initProvide

        function initProvide (vm: Component) {
         const provide = vm.$options.provide
         if (provide) {
         vm._provided = typeof provide === 'function'
         ? provide.call(vm)
         : provide
         }
        }
        

        這個函數跟4.initInjections在同一個inject.js中,也是在傳入參數有provide屬性時做處理,暫時跳過,然后就到了created回調鉤子,最后的vm.$mount接入TODO1;

        今天initMixin到此結束,

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        Vue源碼學習之初始化模塊init.js解析

        Vue源碼學習之初始化模塊init.js解析:我們看到了VUE分了很多模塊(initMixin()stateMixin()eventsMixin()lifecycleMixin()renderMixin()),通過使用Mixin模式,都是使用了JavaScript原型繼承的原理,在Vue的原型上面增加屬性和方法。我們繼續跟著this._init(options)走,這
        推薦度:
        標簽: VUE js 模塊
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲综合色区中文字幕| 亚洲国产精品成人精品无码区 | 亚洲av成人一区二区三区在线观看| 亚洲三级在线播放| 成**人免费一级毛片| 99亚洲乱人伦aⅴ精品| 免费乱理伦在线播放| 国产男女爽爽爽免费视频| 国产l精品国产亚洲区在线观看 | 99re视频精品全部免费| 久久久婷婷五月亚洲97号色| 1000部禁片黄的免费看| 亚洲色无码国产精品网站可下载| 日韩毛片免费在线观看| 美女被免费网站在线视频免费 | 日韩插啊免费视频在线观看| 亚洲精品在线不卡| 成人毛片免费播放| 无码日韩人妻AV一区免费l| 亚洲精品无码专区久久久| 最近中文字幕电影大全免费版| 亚洲免费网站在线观看| 在线观看免费国产视频| 成人av片无码免费天天看| 亚洲视频欧洲视频| 国产高清在线免费视频| 99久久婷婷免费国产综合精品| 久久精品亚洲一区二区三区浴池| 精品熟女少妇AV免费观看| 老司机午夜精品视频在线观看免费| 亚洲深深色噜噜狠狠爱网站| 亚洲一区二区免费视频| 国产精品成人亚洲| 久久久久久a亚洲欧洲AV| 日本午夜免费福利视频| 最近中文字幕大全免费版在线| 亚洲一区二区三区无码国产| 亚洲精品无码永久在线观看| 114级毛片免费观看| 一级毛片免费全部播放| 亚洲午夜国产精品无卡|