组件化是vue中另一个核心思想 所谓组件化 就是把页面拆分成多个组件 每个组件依赖的css js 模板 图片等资源放在一起开发维护 组件是资源独立的 组件在系统内部可以复用 组件和组件之间可以相互嵌套
1. createComponent
上一篇我们了解了普通vnode的生成 现在我们来看看组件vnode的创建 依然是通过_createElement函数创建 里面会做一层判断 得知是组件时调用createComponent方法
此代码截图来自vdom/create-element.js中的_createElement方法 其实这种组件的方式也是我们开发中常用的方式
对于这行代码 我想使用过vue的朋友都不陌生了
接下来我们就看看vue是怎样通过createComponent方法生成组件的vnode的 createComponent方法定义在vdom/create-component.js中
由于createComponent方法比较重要并且代码有点长 所有我会把这个方法分成几段截屏解析 以上代码就是开始的一小段
看完上面代码和解析之后 我们来看看vue是怎样通过extend方法将传进的组件对象转化为组件构造器的
Vue.extend = function (extendOptions: Object): Function {
extendOptions = extendOptions || {}
const Super = this
const SuperId = Super.cid
//缓存构造器 如果多次引用同一个组件 在下次调用后直接返回Sub 就需要重新生成一遍组件构造器
const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
if (cachedCtors[SuperId]) {
return cachedCtors[SuperId]
}
//拿到组件name 校验不合法命名
const name = extendOptions.name || Super.options.name
if (process.env.NODE_ENV !== 'production' && name) {
//validateComponentName 在util/options.js中定义
validateComponentName(name)
}
//定义Sub构造器 用来构造组件
const Sub = function VueComponent (options) {
this._init(options)
}
//继承Vue
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub
Sub.cid = cid++
//options合并 把自身的options和Vue的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 和 computed 这里先不讲
if (Sub.options.props) {
initProps(Sub)
}
if (Sub.options.computed) {
initComputed(Sub)
}
// allow further extension/mixin/plugin usage
//把一些Vue的静态方法赋值给组件构造器Sub
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 是 directive filter component vue用来注册组件 过滤器 指令的静态方法赋值给Sub
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的options做一些赋值
Sub.superOptions = Super.options
Sub.extendOptions = extendOptions
Sub.sealedOptions = extend({}, Sub.options)
// cache constructor
//然后缓存组件构造器Sub
cachedCtors[SuperId] = Sub
//最后返回组件构造器Sub
return Sub
}
我们发现extend就是新建了一个Sub组件构造器 然后继承Vue 并缓存了Vue的静态方法 然后把与组件相关的参数也都挂载到了Sub构造器上 当然这期间有个小优化 如果我们多次使用同一个组件时 组件的构造器会得到复用 不会多次走创建Sub组件构造器的逻辑 而是直接返回原来的组件构造器
知道了vue如何通过组件对象生成组件构造器之后我们继续看createComponent方法
没写中文注释的暂时与我们主要逻辑无关 直接pass 然后我们接着往下看
我们发现组件vnode没有children 当时多出了componentOptions 并且和组件相关的参数都放到了里面 这样看来组件vnode也没有什么神秘的了
2.patch
有了vnode 接下来的操作不用我说大家应该也已经知道下个环节是patch过程 至于具体分析过程就让大家自己去看吧 哈哈哈