vue2源码-- Vue.extend
Posted 在厕所喝茶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue2源码-- Vue.extend相关的知识,希望对你有一定的参考价值。
目录
作用
使用基础的vue
构造器,创建一个子类。参数是包含组件选项的对象。其中data
必须是函数
使用场景
1、所有自定义组件都是通过extend
方法构造出来的
2、实现js调用组件,element-ui
的Message
,MessageBox
等js调用组件,都是通过Vue.extend
实现的
原理分析
1、获取父类的cid
2、从对象参数中获取缓存池,根据父类的cid
判断缓存池中是否已经在之前创建过改子类。是,就直接返回缓存的。这是为了vue
的性能考虑的。对于同一个组件选项对象,反复调用vue.extend
返回的是同一个结果的
3、获取组件的 name 字段,校验组件名字是否合法
4、通过函数的方式创建一个sub
类,并将父类的原型链继承到子类中(原型链继承方式),同时还需要修正constructor
的指向
5、将父类的options
字段和传入组件对象选项进行合并,并保存在子类sub
的options
字段中
6、将父类保存到子类的 super 字段中,确保子类能拿到父类
7、初始化props
,实际上是代理到_props
属性。根组件的 props 是在这里进行数据劫持的。好处就是不用为每个组件的实例都做一层 proxy,这是一种优化手段
8、初始化computed
9、将父类的extend
,mixin
等全局 API 添加到子类中
10、如果name
字段存在,则给子类sub
添加name
字段,方便进行组件递归
11、新增superOptions
,extendOptions
等子类独有的属性
12、将构造出来的子类sub
放进缓存池,key
值为父类的cid
13、返回子类sub
源码
源码位于src/core/global-api/extend.js
/* @flow */
import ASSET_TYPES from 'shared/constants'
import defineComputed, proxy from '../instance/state'
import extend, mergeOptions, validateComponentName from '../util/index'
export function initExtend (Vue: GlobalAPI)
// 每个vue实例都有一个唯一标识
Vue.cid = 0
let cid = 1
// 类继承,作用是创建一个继承自vue类的子类,参数接收的是组件选项的对象
// extendOptions:用户传入的组件选项参数
Vue.extend = function (extendOptions: Object): Function
// 用户传入的一个包含组件选项的对象参数
extendOptions = extendOptions ||
// 父类,即基础的vue类
const Super = this
// 父类id,无论是基础vue类还是继承的vue类,都有一个唯一标识
const SuperId = Super.cid
// 缓存池,用于缓存创建出来的类
const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = )
// 缓存池
if (cachedCtors[SuperId])
// 这一步是为了vue性能考虑,反复调用其实返回的是同一个结果
// 已经创建过的不需要在创建
// 避免多次执行 Vue.extend 的时候对同一个子组件重复构造。
return cachedCtors[SuperId]
// 获取组件选项的name字段
const name = extendOptions.name || Super.options.name
// 校验组件名是否合法
if (process.env.NODE_ENV !== 'production' && name)
validateComponentName(name)
// 创建一个vue类的子类,这个类即将要继承基础vue类
const Sub = function VueComponent (options)
this._init(options)
// 原型链继承方式
// 将父类的原型继承到子类
Sub.prototype = Object.create(Super.prototype)
// 修正constructor的指向
Sub.prototype.constructor = Sub
// id自增,保证唯一标识
Sub.cid = cid++
// 父类的options和传入的子类options进行合并
Sub.options = mergeOptions(
Super.options,
extendOptions
)
// 将父类保存到子类的super字段中,确保子类能拿到父类
Sub['super'] = Super
// 初始化props,根组件的props是在这里进行数据劫持的。好处就是不用为每个组件的实例都做一层proxy,这是一种优化手段
if (Sub.options.props)
// 初始化props其实就是代理到原型的_props属性
initProps(Sub)
// 初始化computed
if (Sub.options.computed)
initComputed(Sub)
// 将父类的一些属性添加到子类中
Sub.extend = Super.extend
Sub.mixin = Super.mixin
Sub.use = Super.use
// 'component',
// 'directive',
// 'filter'
ASSET_TYPES.forEach(function (type)
Sub[type] = Super[type]
)
// 方便组件进行递归调用
if (name)
Sub.options.components[name] = Sub
// 新增子类独有属性
Sub.superOptions = Super.options
Sub.extendOptions = extendOptions
Sub.sealedOptions = extend(, Sub.options)
// 放入缓存池
cachedCtors[SuperId] = Sub
return Sub
function initProps (Comp)
const props = Comp.options.props
for (const key in props)
// 将props代理到原型上面的_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])
以上是关于vue2源码-- Vue.extend的主要内容,如果未能解决你的问题,请参考以下文章