• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答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源碼解讀之Component組件注冊的實現

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

    Vue源碼解讀之Component組件注冊的實現

    Vue源碼解讀之Component組件注冊的實現:什么是組件? 組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以表現為用 is 特性進行了擴展的原生 HTML 元素。
    推薦度:
    導讀Vue源碼解讀之Component組件注冊的實現:什么是組件? 組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以表現為用 is 特性進行了擴展的原生 HTML 元素。

    什么是組件?

    組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以表現為用 is 特性進行了擴展的原生 HTML 元素。

    所有的 Vue 組件同時也都是 Vue 的實例,所以可接受相同的選項對象 (除了一些根級特有的選項) 并提供相同的生命周期鉤子。

    Vue可以有全局注冊和局部注冊兩種方式來注冊組件。

    全局注冊

    注冊方式

    全局注冊有以下兩種注冊方式:

    通過Vue.component 直接注冊。

    Vue.component('button-counter', {
     //data選項必須是一個函數
     data: function () {
     return {
     count: 0
     }
     },
     template:'#clickBtn'
     })

    通過Vue.extend來注冊。

     var buttonComponent = Vue.extend({
     name:'button-counter',
     data: function () {
     return {
     count: 0
     }
     },
     template:'#clickBtn'
     });
     Vue.component('button-counter', buttonComponent);

    具體過程

    Vue初始化時,initGlobalAPI通過調用initAssetRegisters()進行組件注冊。

    function initAssetRegisters (Vue) {
     // 創建組件注冊的方法
     // ASSET_TYPES在Vue內部定義,var ASSET_TYPES = ['component','directive','filter'];
     ASSET_TYPES.forEach(function (type) {
     Vue[type] = function (
     id,
     definition
     ) {
     //這里的definition指的是定義(Function或Object),是函數或者對象
     //如果definition不存在,直接返回options內type和id對應的
     //這里的options是指全局的組件,指令和過濾器,見圖一
     if (!definition) {
     return this.options[type + 's'][id]
     } else {
     /* istanbul ignore if */
     if ("development" !== 'production' && type === 'component') {
     validateComponentName(id);
     }
     // 如果是component(組件)方法,并且definition是對象
     if (type === 'component' && isPlainObject(definition)) {
     definition.name = definition.name || id;
     //通過this.options._base.extend方法(也就是Vue.extend方法)將定義對象轉化為構造器。
     //Vue.options._base = Vue;
     definition = this.options._base.extend(definition);
     }
     if (type === 'directive' && typeof definition === 'function') {
     definition = { bind: definition, update: definition };
     }
     // 將構造器賦值給 this.options[‘component'+ 's'][id]
     //全局的組件,指令和過濾器,統一掛在vue.options上。在init的時候利用mergeOptions合并策略侵入實例,供實例使用。
     this.options[type + 's'][id] = definition;
     return definition
     }
     };
     });
    }

    圖一:

    initAssetRegisters里面通過this.options._base.extend方法將定義對象轉化為構造器,而options._base.extend其實就是Vue.extend。接下來我們就看一下Vue.extend做了什么。

    Vue.extend = function (extendOptions) {
     extendOptions = extendOptions || {};
     var Super = this;
     var SuperId = Super.cid;
     //組件緩存
     var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {});
     //如果組件已經被緩存在extendOptions上則直接取出
     if (cachedCtors[SuperId]) {
     return cachedCtors[SuperId]
     }
    
     //如果有name屬性,檢驗name拼寫是否合法
     var name = extendOptions.name || Super.options.name;
     if ("development" !== 'production' && name) {
     validateComponentName(name);
     }
    
     var Sub = function VueComponent (options) {
     this._init(options);
     };
     //將vue上原型的方法掛在Sub.prototype中,Sub的實例同時也繼承了vue.prototype上的所有屬性和方法。
     //關于 prototype的學習:http://www.cnblogs.com/dolphinX/p/3286177.html
     Sub.prototype = Object.create(Super.prototype);
     //Sub構造函數修正,學習于https://www.cnblogs.com/SheilaSun/p/4397918.html
     Sub.prototype.constructor = Sub;
     Sub.cid = cid++;
     //通過vue的合并策略合并添加項到新的構造器上
     Sub.options = mergeOptions(
     Super.options,
     extendOptions
     );
     //緩存父構造器
     Sub['super'] = Super;
    
     // 處理props和computed響應式配置項
     if (Sub.options.props) {
     initProps$1(Sub);
     }
     if (Sub.options.computed) {
     initComputed$1(Sub);
     }
    
     // allow further extension/mixin/plugin usage
     Sub.extend = Super.extend;
     Sub.mixin = Super.mixin;
     Sub.use = Super.use;
    
     //在新的構造器上掛上vue的工具方法
     ASSET_TYPES.forEach(function (type) {
     Sub[type] = Super[type];
     });
     // enable recursive self-lookup
     if (name) {
     Sub.options.components[name] = Sub;
     }
    
     // keep a reference to the super options at extension time.
     // later at instantiation we can check if Super's options have
     // been updated.
     Sub.superOptions = Super.options;
     Sub.extendOptions = extendOptions;
     Sub.sealedOptions = extend({}, Sub.options);
    
     //緩存組件構造器在extendOptions上
     cachedCtors[SuperId] = Sub;
     return Sub
     };

    vue.extend返回了一個帶有附加Option的vue構造器。這個構造器被命名為Sub,等待render時候初始化。

    initAssetRegisters完成之后,options下掛載了全局組件button-counter,如圖:

    接下來調用new Vue()渲染vue整體的生命周期

    局部注冊

    如果不需要全局注冊,或者是讓組件使用在其它組件內,可以用選項對象的components屬性實現局部注冊。

    注冊方式

    new Vue({
     el: '#components-demo',
     components:{
     'button-counter':{
     template:'#clickBtn',
     data: function () {
     return {
     count: 0
     }
     }
     }
     }
     })

    具體過程

    Vue局部組件注冊也是通過initAssetRegisters()方法調用Vue.extend,不同的是在createComponent()時,initMixin()里面有判斷

    if (options && options._isComponent) {
     //因為Vue動態合并策略非常慢,并且內部組件的選項都不需要特殊處理。
     //調用initInternalComponent快捷方法,內部組件實例化。
     initInternalComponent(vm, options);
     }
     else {
     vm.$options = mergeOptions(
     resolveConstructorOptions(vm.constructor),
     options || {},
     vm
     );
     }
    function initInternalComponent (vm, options) {
     var opts = vm.$options = Object.create(vm.constructor.options);
     // 這樣做是因為它比動態枚舉更快。
     var parentVnode = options._parentVnode;
     opts.parent = options.parent;
     opts._parentVnode = parentVnode;
    
     var vnodeComponentOptions = parentVnode.componentOptions;
     opts.propsData = vnodeComponentOptions.propsData;
     opts._parentListeners = vnodeComponentOptions.listeners;
     opts._renderChildren = vnodeComponentOptions.children;
     opts._componentTag = vnodeComponentOptions.tag;
    
     if (options.render) {
     opts.render = options.render;
     opts.staticRenderFns = options.staticRenderFns;
     }
    }

    opts的結構如圖所示:

    局部注冊和全局注冊不同的是,只有該類型的組件才可以訪問局部注冊的子組件,而全局注冊是擴展到 Vue.options 下。在所有組件創建的過程中,都會從全局的 Vue.options.components 擴展到當前組件的 vm.$options.components 下,這就是全局注冊的組件能被任意使用的原因。

    組件名定義

    定義組件名的方式有兩種:

    使用短橫線形式

    Vue.component('button-counter', {})

    引用這個自定義元素時,必須用 <button-counter></button-counter>

    使用駝峰的形式

    Vue.component('buttonCounter', { })

    此時在引用這個自定義元素時,兩種命名方法都可以使用。也就是說,<buttonCounter><button-counter> 都是可行的。

    注意,直接在 DOM (即非字符串的模板) 中使用時只有短橫線是有效的。如下:

    <div id="components-demo">
     <button-counter></button-counter>
    </div>

    可參考:https://www.gxlcms.com/article/144050.htm

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

    文檔

    Vue源碼解讀之Component組件注冊的實現

    Vue源碼解讀之Component組件注冊的實現:什么是組件? 組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以表現為用 is 特性進行了擴展的原生 HTML 元素。
    推薦度:
    標簽: VUE 代碼 組件
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 久久久久成人精品无码| 久久久久人妻精品一区二区三区| 久久精品无码免费不卡| 99久久精品国产免看国产一区| 四虎精品免费永久免费视频| 午夜精品成年片色多多| 精品无码日韩一区二区三区不卡| 麻豆国内精品久久久久久| 欧美一区二区精品系列在线观看| 日韩精品无码免费一区二区三区 | 亚洲国产精品18久久久久久| 国产精品综合专区中文字幕免费播放 | 国内精品久久久久久野外| 久久亚洲日韩精品一区二区三区| 久久久久久国产精品美女| 国产成人精品免费大全| 欧美精品第欧美第12页| 55夜色66夜色国产精品视频| 色妞ww精品视频7777| 亚洲欧美日韩国产一区二区三区精品| 国产精品无码不卡一区二区三区 | 国产精品亚洲精品日韩已方| 亚洲国产精品国自产拍电影| 国产精品亚洲午夜一区二区三区| 国产精品人成在线播放新网站 | 国产三级精品三级在专区| 最新国产精品亚洲| 欧美成人精品一级高清片| 国产精品一久久香蕉产线看| 国产精品你懂的| 免费视频精品一区二区三区| 亚洲国产精品免费视频| 一区二区三区精品国产欧美| 麻豆精品成人免费国产片| 青青草国产精品久久| 欧美成人精品一级高清片| 91国内揄拍国内精品情侣对白 | 国产欧美日韩精品a在线观看| 久久er99热精品一区二区| 精品无码一区二区三区爱欲九九 | 99热成人精品国产免男男|