欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue源碼解讀之Component組件注冊(cè)的實(shí)現(xiàn)

 更新時(shí)間:2018年08月24日 11:10:20   作者:花花呀  
這篇文章主要介紹了Vue源碼解讀之Component組件注冊(cè)的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

什么是組件?

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

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

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

全局注冊(cè)

注冊(cè)方式

全局注冊(cè)有以下兩種注冊(cè)方式:

通過Vue.component 直接注冊(cè)。

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

通過Vue.extend來注冊(cè)。

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

具體過程

Vue初始化時(shí),initGlobalAPI通過調(diào)用initAssetRegisters()進(jìn)行組件注冊(cè)。

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

圖一:

initAssetRegisters里面通過this.options._base.extend方法將定義對(duì)象轉(zhuǎn)化為構(gòu)造器,而options._base.extend其實(shí)就是Vue.extend。接下來我們就看一下Vue.extend做了什么。

Vue.extend = function (extendOptions) {
  extendOptions = extendOptions || {};
  var Super = this;
  var SuperId = Super.cid;
  //組件緩存
  var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {});
  //如果組件已經(jīng)被緩存在extendOptions上則直接取出
  if (cachedCtors[SuperId]) {
   return cachedCtors[SuperId]
  }

  //如果有name屬性,檢驗(yàn)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的實(shí)例同時(shí)也繼承了vue.prototype上的所有屬性和方法。
  //關(guān)于 prototype的學(xué)習(xí):http://www.cnblogs.com/dolphinX/p/3286177.html
  Sub.prototype = Object.create(Super.prototype);
  //Sub構(gòu)造函數(shù)修正,學(xué)習(xí)于https://www.cnblogs.com/SheilaSun/p/4397918.html
  Sub.prototype.constructor = Sub;
  Sub.cid = cid++;
  //通過vue的合并策略合并添加項(xiàng)到新的構(gòu)造器上
  Sub.options = mergeOptions(
   Super.options,
   extendOptions
  );
  //緩存父構(gòu)造器
  Sub['super'] = Super;

  // 處理props和computed響應(yīng)式配置項(xiàng)
  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;

  //在新的構(gòu)造器上掛上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);

  //緩存組件構(gòu)造器在extendOptions上
  cachedCtors[SuperId] = Sub;
  return Sub
 };

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

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

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

局部注冊(cè)

如果不需要全局注冊(cè),或者是讓組件使用在其它組件內(nèi),可以用選項(xiàng)對(duì)象的components屬性實(shí)現(xiàn)局部注冊(cè)。

注冊(cè)方式

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

具體過程

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

if (options && options._isComponent) {
   //因?yàn)閂ue動(dòng)態(tài)合并策略非常慢,并且內(nèi)部組件的選項(xiàng)都不需要特殊處理。
   //調(diào)用initInternalComponent快捷方法,內(nèi)部組件實(shí)例化。
   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);
 // 這樣做是因?yàn)樗葎?dòng)態(tài)枚舉更快。
 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的結(jié)構(gòu)如圖所示:

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

組件名定義

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

使用短橫線形式

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

引用這個(gè)自定義元素時(shí),必須用 <button-counter></button-counter>

使用駝峰的形式

Vue.component('buttonCounter', { })

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

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

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

可參考:http://www.dbjr.com.cn/article/144050.htm

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解如何在你的Vue項(xiàng)目配置vux

    詳解如何在你的Vue項(xiàng)目配置vux

    這篇文章主要介紹了詳解如何在你的Vue項(xiàng)目配置vux,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • Vue3動(dòng)態(tài)路由(響應(yīng)式帶參數(shù)的路由)變更頁面不刷新的問題解決辦法

    Vue3動(dòng)態(tài)路由(響應(yīng)式帶參數(shù)的路由)變更頁面不刷新的問題解決辦法

    問題來源是因?yàn)槲业拈_源項(xiàng)目Maple-Boot項(xiàng)目的網(wǎng)站前端,因?yàn)轫?xiàng)目主打的內(nèi)容發(fā)布展示,所以其中的內(nèi)容列表頁會(huì)根據(jù)不同的菜單進(jìn)行渲染不同的路由,本文降介紹Vue3動(dòng)態(tài)路由變更頁面不刷新的問題解決辦法,需要的朋友可以參考下
    2024-07-07
  • vue項(xiàng)目實(shí)現(xiàn)按鈕可隨意移動(dòng)

    vue項(xiàng)目實(shí)現(xiàn)按鈕可隨意移動(dòng)

    這篇文章主要為大家詳細(xì)介紹了vue項(xiàng)目實(shí)現(xiàn)按鈕可隨意移動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • VUE?mixin?使用示例詳解

    VUE?mixin?使用示例詳解

    混入mixin提供了一種非常靈活的方式,來分發(fā)Vue組件中的可復(fù)用功能,一個(gè)混入對(duì)象可以包含任意組件選項(xiàng),接下來通過本文給大家介紹VUE?mixin?使用,需要的朋友可以參考下
    2022-08-08
  • antd的選擇框如何增加tab選中的方法示例

    antd的選擇框如何增加tab選中的方法示例

    這篇文章主要為大家介紹了antd的選擇框如何增加tab選中的方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • axios實(shí)現(xiàn)文件上傳并獲取進(jìn)度

    axios實(shí)現(xiàn)文件上傳并獲取進(jìn)度

    這篇文章主要為大家詳細(xì)介紹了axios實(shí)現(xiàn)文件上傳并獲取進(jìn)度,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • vue簡(jiǎn)單的二維數(shù)組循環(huán)嵌套方式

    vue簡(jiǎn)單的二維數(shù)組循環(huán)嵌套方式

    這篇文章主要介紹了vue簡(jiǎn)單的二維數(shù)組循環(huán)嵌套方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue調(diào)試神器vue-devtools安裝方法

    Vue調(diào)試神器vue-devtools安裝方法

    本篇文章主要介紹了Vue調(diào)試神器vue-devtools安裝方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • Vue3中toRef與toRefs的區(qū)別

    Vue3中toRef與toRefs的區(qū)別

    這篇文章主要介紹了Vue3中toRef與toRefs的區(qū)別,toRefs與toRef功能一致,但可以批量創(chuàng)建多個(gè)ref對(duì)象,需要注意的是它只會(huì)解析對(duì)象的第一層屬性,語法直接傳入對(duì)象 toRefs,下面更多內(nèi)容的介紹需要的小伙伴可以參考一下
    2022-03-03
  • Vue實(shí)現(xiàn)滑動(dòng)驗(yàn)證功能

    Vue實(shí)現(xiàn)滑動(dòng)驗(yàn)證功能

    這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)滑動(dòng)驗(yàn)證功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評(píng)論