Vue 소스 코드 판독 의 Component 구성 요소 등록 실현

구성 요소 가 무엇 입 니까?
구성 요소(Component)는 Vue.js 의 가장 강력 한 기능 중의 하나 이다.구성 요 소 는 HTML 요 소 를 확장 할 수 있 고 재 활용 가능 한 코드 를 패키지 할 수 있 습 니 다.높 은 차원 에서 구성 요 소 는 사용자 정의 요소 이 고 Vue.js 의 컴 파일 러 는 특수 기능 을 추가 합 니 다.어떤 경우 에는 구성 요소 도 is 특성 으로 확 장 된 원생 HTML 요소 로 표현 할 수 있다.
모든 Vue 구성 요 소 는 Vue 의 인 스 턴 스 이기 때문에 같은 옵션 대상(루트 특유 의 옵션 제외)을 받 아들 이 고 같은 수명 주기 갈 고 리 를 제공 할 수 있 습 니 다.
Vue 는 전역 등록 과 부분 등록 두 가지 방식 으로 구성 요 소 를 등록 할 수 있 습 니 다.
전역 등록
등록 방식
전역 등록 은 다음 과 같은 두 가지 등록 방식 이 있 습 니 다.
Vue.coponent 를 통 해 직접 등록 합 니 다.

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
   }
  };
 });
}
그림 1:

initAsset Registers 에서 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 는 추가 옵션 이 있 는 vue 구조 기 를 되 돌려 주 었 습 니 다.이 구조 기 는 Sub 라 고 명명 되 어 render 를 기다 릴 때 초기 화 됩 니 다.
initAsset Registers 가 완 료 된 후 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.coponents 에서 현재 구성 요소 의 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.jb51.net/article/144050.htm
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기