在我们日常工作中,经常会使用一些UI框架,比如:vant、elementui、antdesign等,但是在使用时,一般需要手动import一下,那有没有可能,我不通过import直接在全局调用呢,就像一个全局方法一样。
vue就为我们提供了这样的一个Api -- Vue.extend(options)。创建一个“子类”。参数是一个包含组件选项的对象。我们可以将组建封装成函数的形式,直接通过调用全局方法的形式调用它。注意:data选项是特例,在Vue.extend()中它必须是函数。
Vue.extend以组件为入参,那么首先我们要先写一个组件,这个组件要包含一些基本的默认值,要有展示toast与隐藏toast的控制,可以设置一个状态值,通过监控这个值来展示与隐藏。组件代码如下:
<template>
<div v-show="visible" class="toast">
{{ message }}
</div>
</template>
<script>
export default {
name: 'toast',
data() {
return {
message: '', // 默认的提示信息
visible: false, // 是否可见
duration: 3000, //默认三秒
timer: null, // 计时的,用作判断
closed: false, // 判断是否已经关闭
};
},
watch: {
closed(newVal) { // 监听closed的值变化,用来控制组件的展示隐藏,及销毁
if (newVal) {
this.visible = false;
this.destroyElement();
}
},
},
mounted() {
this.startTimer(); // 组件挂载后,先做展示
},
methods: {
startTimer() {
this.visible = true;
this.timer = setTimeout(() => {
if (!this.closed) {
this.closed = true;
clearTimeout(this.timer);
}
}, this.duration);
},
destroyElement() { // 销毁组件
this.$destroy();
this.$el.parentNode.removeChild(this.$el); // 将组建从dom节点移除
},
},
};
</script>
上面是一个toast组件所需要的模板与js处理,那么如果做到全局直接调用呢。Vue.extend可以生成一个组件的构造函数,可以通过 new 的方式,创建一个组件实例。再通过实例的挂载及层级的控制,来做处理,代码如下:
import Vue from 'vue';
import Toast from './toast.vue';
let ToastConstructor = Vue.extend(Toast);
let instance // 实例对象
let seed = 0; // 确定有多少这样的实例,控制层级
const ToastDialog = (options ={})=>{
if (typeof options === 'string') { // 支持只传入文案提示
options = {
message: options
}
}
let id = `toast_${seed++}`
instance = new ToastConstructor({
data:options // 可以与组件内部的data进行合并,如果key相同可以将原来的值替换掉
})
console.log(instance,'instance is ----')
instance.id = id;
/* 因为还没有具体的dom节点可以挂载此处$mount没有提供参数,
模板将被渲染为文档之外的的元素,必须使用原生DOM API把它插入文档中 */
instance.vm = instance.$mount();
document.body.appendChild(instance.vm.$el); // 将实例挂载到dom上
instance.vm.visible = true;
instance.dom = instance.vm.$el;
instance.dom.style.zIndex = 999 + seed;
console.log(instance,'instance is ----');
return instance.vm;
}
export default ToastDialog;
做完以上这些,还没有完事,需要将该实例方法,添加到vue的全局方法中:
Vue.prototype.$toast = Toast;
然后就哪里需要哪里调用就可以了:
this.$toast('记得吃饭···')