# Vue.extend
# 用法回顾
其用法如下:
Vue.extend( options )
成功
1
参数:
{Object} options
作用:
使用基础
Vue
构造器,创建一个“子类”。参数是一个包含组件选项的对象。data
选项是特例,需要注意 - 在Vue.extend()
中它必须是函数<div id="mount-point"></div>
成功1// 创建构造器 var Profile = Vue.extend({ template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>', data: function () { return { firstName: 'Walter', lastName: 'White', alias: 'Heisenberg' } } }) // 创建 Profile 实例,并挂载到一个元素上。 new Profile().$mount('#mount-point')
成功1
2
3
4
5
6
7
8
9
10
11
12
13结果如下:
<p>Walter White aka Heisenberg</p>
成功1
# 原理分析
通过用法回顾,我们知道Vue.extend
的作用是创建一个子类,所以实现思路就是创建一个子类,然后继承Vue构造函数的一些功能。
虽然在平时的开发中很少用到它,但是在 Vue 源码内部,extend
方法却很重要。因为在 Vue 中,组件的本质就是通过 extend
方法创建出来的 Vue 构造函数的子类构造函数。
// src/core/global-api/extend.js export function initExtend (Vue: GlobalAPI) { Vue.cid = 0 let cid = 1 Vue.extend = function (extendOptions: Object): Function { // 初始化用户传入的参数 extendOptions = extendOptions || {} // 指向父类 const Super = this // 父类cid const SuperId = Super.cid // 获取缓存项 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(name) } // 创建子类Sub const Sub = function VueComponent (options) { // 调用原型上的_init this._init(options) } // 继承父类原型方法 Sub.prototype = Object.create(Super.prototype) Sub.prototype.constructor = Sub // 添加子类唯一标识 Sub.cid = cid++ // 合并父类和子类选项并设置为子类选项 Sub.options = mergeOptions( Super.options, extendOptions ) // 将父类存到子类的super字段中 Sub['super'] = Super // 初始化props if (Sub.options.props) { initProps(Sub) } // 初始化computed if (Sub.options.computed) { initComputed(Sub) } // 复制父类的extend/mixin/use Sub.extend = Super.extend Sub.mixin = Super.mixin Sub.use = Super.use // 复制父类的'component','directive', 'filter' ASSET_TYPES.forEach(function (type) { Sub[type] = Super[type] }) // enable recursive self-lookup if (name) { Sub.options.components[name] = Sub } // 定义子类特殊的属性 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 // 将key代理到_props for (const key in props) { proxy(Comp.prototype, `_props`, key) } } function initComputed (Comp) { const computed = Comp.options.computed // 遍历computed,重新定义一遍 for (const key in computed) { defineComputed(Comp.prototype, key, computed[key]) } }
成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
上述代码的逻辑较为简单,跟我们之前分析的一样,创建一个子类,然后继承Vue构造函数的一些功能。里面大量的初始化方法,我们在生命周期篇都已经介绍过了,此处不再重复介绍
这里需要注意的是,Vue为了性能考虑,在Vue.extend
方法中增加了缓存策略。反复调用Vue.extend
会同一个结果。
← 前言 Vue.nextTick →