在思考表單集成方案的時候,咱們知道,在配置json生成form組件的時候,總會經過type與form組件一一對應來找到對應的組件,也就是說,在聲明json form類型以前,須要提早開發對應的組件,或者動態掛載組件。在vue框架下,想要作到持續集成,能夠將組件聲明爲全局組件,而後在json轉化爲組件時候經過name來加載對應組件。但這樣作的缺陷是,沒法動態給第三方組件掛載公共的屬性與事件;在設計上看,將擴展組件的功能收斂至統一入口,再借助vue動態實例化組件的能力,這樣作有利於後續持續集成,減小開發上的反作用,使整個庫的開發思路可控。vue
Vue.extend(extendOptions)
json
經過調用vue.extend可返回一個vue的子類緩存
function extend(extendOptions){
extendOptions = extendOptions || {}
// this->vue
const Super = this
const SuperId = Super.cid
// 使用父類的id做爲緩存的key
// 只要父類id相同,每次調用會返回相同的子類
const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
if (cachedCtors[SuperId]) {
return cachedCtors[SuperId]
}
// 對name命名方式進行校驗
// /^[a-zA-Z][\w-]*/
const name = extendOptions.name || Super.options.name
if (process.env.NODE_ENV !== 'production' && name) {
validateComponentName(name)
}
const Sub = function VueComponent (options) {
// vue._init
this._init(options)
}
// 繼承父類構造函數
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub
Sub.cid = cid++
// 合併父類的options
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.
// 初始化props
// 將props掛載在原型對象的_props屬性下
if (Sub.options.props) {
initProps(Sub)
}
// 初始化computed
// 將初始化computed掛載在原型對象下
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 } } 複製代碼
首先,同直接調用vue
構造函數實例化組件來對比,vue.extend
在開始先作來一層緩存校驗,若是該extendOptions
已經存在組件的構造函數,那麼會直接返回該構造函數,避免同一個組件反覆構建組件生成器函數,同時使用父類的id做爲緩存標時。bash
當未命中緩存時,會進入建立組件生成器函數的過程,首先對組件名稱進行校驗,名稱首字母開頭必須是大小寫英文,後續字符支持大小寫下劃線(_)及間隔線(-)。框架
名稱校驗經過後,先聲明一個組件對構造函數:函數
const Sub = function VueComponent (options) {
// Vue.prototype._init
this._init(options)
}
複製代碼
讓Sub函數經過原型繼承父類(Vue),並將傳入的extendOptions
與父類的options
配置項進行合併,而後保存父類的構造函數至super
屬性。ui
當options
中掛載props
與computed
等屬性時,須要單獨進行處理,處理的內部細節與結果在後續的vue探究
文章再作深刻討論。this
當經過原型繼承父類,初始化props
與computed
成員屬性以後,還須要繼承父類的靜態方法,如mixin、extend、use、component、directive、filter
等。spa
最後在子類構造函數上新增superOptions、extendOptions、sealedOptions
以備實例化的時候使用,再緩存該新生成子類(組件構造函數)。prototype
總的來看,vue.extend方法本質是建立了一個Sub函數,並繼承了父類(父組件或者Vue構造函數)的相關屬性或者方法。
調用component註冊一個局部或者全局組件,並設置組件的別名。
// 在Vue中,component、filter、directive是混合在一塊兒實現的,這裏拆開
Vue.options['component'] = Object.create(null)
Vue.component = function(id, definition){
if(!definition){
return this.options['components'][id]
}else{
if(isPlainObject(definition)){
definition.name = definition.name || id
definition = Vue.extend(definition)
}
this.options['components'][id] = definition
return definition
}
}
複製代碼
component方法本質是調用extend方法構造一個子類,並將該子類保存在options的components的對應的key下面,在SFC
中註冊的。
文章內容若有錯誤,敬請諒解,但願能夠不吝賜教
轉載請註明出處