Vue.component source code interpretation
// Source code location: vue/src/core/global-api/assets.js import { ASSET_TYPES } from 'shared/constants' import { isPlainObject, validateComponentName } from '.. /util/index' /* ASSET_TYPES stores [' Component ','directive','filter'] to add static methods to Vue vue.directive = vue.filter = function(id,{***}) */ export function initAssetRegisters (Vue: GlobalAPI) { ASSET_TYPES.forEach(type => { Vue[type] = function ( id: string, definition: Function | Object ): Function | Object | void { if (! definition) { return this.options[type + 's'][id] } else { /* istanbul ignore if */ if (process.env.NODE_ENV ! == 'production' && type === 'Component ') {// validateComponentName(ID)} if (type ===' Component '&& IsPlainObject (definition)) {definition. The name = definition. The name | | id / / create a component constructor definition = this.options._base.extend(definition) } if (type === 'directive' && typeof definition === 'function') { definition = { bind: definition, update: This. Options [type + 's'][id] = definition return definition} // Assign the definition result to the static property 'type+s' of the component constructor. }})}Copy the code
Result of executing initAssetRegisters (ignoring ‘directive’ and ‘filter’ this time)
Vue.component=function(id,definition){ if (! Definition) {return this.options[type + 's'][id]} else {// Production validates component name if (process.env.node_env! == 'production' && type === 'component') { validateComponentName(id) } if (type === 'component' && IsPlainObject (definition)) {definition. The name = definition. The name | | id / / create a component constructor definition = This.options._base.extend (definition)} // Assigns the processed definition result to this.options[components][id] = on the static property 'type+ S' of the component constructor definition return definition } } }Copy the code
ValidateComponentName Detection component specification
unicodeRegExp.source = a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u30 Physical network loss: 01-\uD7FF\ UF900-\ uFDCF\ UFDF0-\ uFFFD //unicodeRegExp = / A-za-zA-ZA-A-ZA-A-ZONE-A/export physical network loss: 1-\uD7FF\ UF900-\ uFDCF\ UFDF0-\ uFFFD string) { //! New RegExp (` ^ [a zA - Z] [\ \ - \ \. 0-9 _a - zA - Z.A - O] * $`). The test (name) if (! new RegExp(`^[a-zA-Z][\\-\\.0-9_${unicodeRegExp.source}]*$`).test(name)) { warn( 'Invalid component name: "' + name + '". Component names ' + 'should conform to valid custom element name in html5 specification.' ) } if (isBuiltInTag(name) || config.isReservedTag(name)) { warn( 'Do not use built-in or reserved HTML elements as component ' + 'id: ' + name ) } }Copy the code
this.options._base === Vue
import { ASSET_TYPES } from 'shared/constants' import { defineComputed, proxy } from '.. /instance/state' import { extend, mergeOptions, validateComponentName } from '.. /util/index' /* Sub inherits properties or methods from the super. prototype prototype chain and assigns static properties of the Super constructor to Sub sub. superOptions = super. options(subclass stores options from the parent class) sub.extendOptions = extendOptions sub. sealedOptions = extend({}, Subclass */ export function initExtend (Vue: GlobalAPI) { /** * Each instance constructor, including Vue, has a unique * cid. This enables us to create wrapped "child * constructors" for prototypal inheritance and cache them. */ Vue.cid = 0 let cid = 1 /** * Class inheritance */ Vue.extend = function (extendOptions: Object): Function { extendOptions = extendOptions || {} const Super = this const SuperId = Super.cid const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {}) if (cachedCtors[SuperId]) { return cachedCtors[SuperId] } const name = extendOptions.name || Super.options.name if (process.env.NODE_ENV ! == 'production' && name) { validateComponentName(name) } const Sub = function VueComponent (options) { this._init(options) } Sub.prototype = Object.create(Super.prototype) Sub.prototype.constructor = Sub Sub.cid = cid++ Sub.options = mergeOptions( Super.options, extendOptions ) Sub['super'] = Super // For props and computed properties, we define the proxy getters on // the Vue instances at extension time, on the extended prototype. This // avoids Object.defineProperty calls for each instance created. if (Sub.options.props) { initProps(Sub) } if (Sub.options.computed) { initComputed(Sub) } // allow further extension/mixin/plugin usage Sub.extend = Super.extend Sub.mixin = Super.mixin Sub.use = Super.use // create asset registers, so extended classes // can have their private assets too. 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) // cache constructor cachedCtors[SuperId] = Sub return Sub } } function initProps (Comp) { const props = Comp.options.props for (const key in props) { proxy(Comp.prototype, `_props`, key) } } function initComputed (Comp) { const computed = Comp.options.computed for (const key in computed) { defineComputed(Comp.prototype, key, computed[key]) } }Copy the code