前言
Vue.extend作为一全局api,作为我们去实现编程式组件的重要途径,所以我们通过源码学习的方式,来加深对Vue.extend函数的理解,通过以下几个问题的解读,来对Vue.extend深入学习
- Vue.extend在Vue中的用途?
- 讲解下Vue.extend的内部实现?
- 实现一个编程式组件,具体的思路应该式怎样?
Vue.extend的深入
基本用法
参数:[Object] options
用法:使用基础Vue构造器,创建一个”子类”,参数式一个包含组件选项的对象,data选项是特例,需要注意⚠️下【Vue.extend()中data必须是函数。】
1 | // 创建构造器 |
结果如下:
1 | <p>Walter White aka Heisenberg</p> |
源码分析
以下是Vue.extend的源码
1 | Vue.extend = function (extendOptions: Object): Function { |
源码导读
1、
1 | extendOptions = extendOptions || {} |
首先,extendOptions使用我们传递进入的模版,这里面的this
就是调用extend的对象,也就是Vue
,然后将其保存到Super变量中,SuperId变量保存着Vue中的唯一标识(每个实例都有自己唯一的cid
)。
2、
1 | const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {}) |
这一段是作为缓存策略用的,后面提及到。
3、
1 | const name = extendOptions.name || Super.options.name |
看传递进来的模版中是否有包含name属性,如果没有则用父组件的name,然后对name通过validateComponent函数进行校验,主要判断就是name不能是html元素或者非法命名。
4、
1 | Sub.prototype = Object.create(Super.prototype) |
👆创建一个子类Sub,通过继承的方式,使得Sub拥有了Vue的能力,并且添加了唯一id(每个组件的唯一标识符)
5、
1 | Sub.options = mergeOptions( |
👆调用了mergeOptions函数,实现了父类选项与子类选项的合并,并且子类的super指向了父类
6、
1 | if (Sub.options.props) { |
👆初始化props和computed
7、
1 | // allow further extension/mixin/plugin usage |
👆将父类的方法复制到子类,包括有extend, mixin, use, component, directive, filter
,还有新增属性superOptions, extendOptions
8、
1 | // cache constructor |
👆与之前的代码结合,将父类的id保存在子类的属性上,属性值为子类,在之前会进行判断如果构造过子类,就直接将父类保存过的id值返回了,避免重复初始化Sub
- 整体来说,就是创建了一个Sub函数并继承了父Vue或其孩子组件 *
手动实现一个编程式组件
一般我们在使用组件的时候,都会现注册组件,再在模版中使用,如果我们想要想element-ui
中的$message那样子直接通过命令来调用,那该有多方便吖1
this.$message.success('成功');
创建一个组件,用于编程式调用的
👆组件比较简单,就是实现一个简单的吐司功能1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// toast.vue
<template>
<div v-show="isShow">{{ message }}</div>
</template>
<script>
export default{
data(){
return {
message: '',
isShow: false
}
},
methods: {
show(message, duration = 3000){
this.message = message;
this.isShow = true;
setTimeout(() => {
this.isShow = falsel
this.message = '';
}, duration);
}
}
}
</script>实现编程式
上述定义了一个插件,然后我们在main.js应用程序入口处,将插件进行使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// plugins/toast.js
import Toast from './toast';
export default {
install(Vue){
// 创建Sub构造器
const ToastConstrutor = Vue.extend(Toast);
// 以new的方式,根据Sub构造器,创建一个游离的组件实例
const toast = new ToastConstrutor();
// 获取到组件的html内容
const toastTpl = toast.$mount().$el;
// 将html内容插入到document中
document.body.appendChild(toastTpl);
Vue.prototype.$toast = toast;
}
}在main.js中注册
1
2
3import Vue from 'vue';
import toast from '/plugins/toast.js';
Vue.use(toast);在实际的组件中使用
这样子我们就可以在项目的各个位置上调用了1
this.$toast.show('你真帅吖!!!');
总结
Vue.extend总体来说其实就是创建一个类(函数)来继承于父类,顶级一定是Vue,这个类就表示一个组件,我们可以通过new
的方式来创建。
最后更新: 2023年03月13日 08:45
原始链接: https://www.91temaichang.com/2021/05/11/vue-extend-study/