最近的项目中,需要自己去手写一个全局的弹窗组件,在下面贴出自己的代码。
组件写的比较简单 notice.vue
<template>
<div class="alert">
<div class="alert-container" v-for="item in alerts" :key="item.id">
<div class="alert-content">{{item.content}}</div>
</div>
</div>
</template>
<script>
export default {
name:'notice',
data() {
return {
alerts: []
}
},
created () {
// id自增控制
this.id = 0;
},
methods: {
add(options) {
const id = 'id_' + this.id++;
const _alert = {...options,id:id};
this.alerts.push(_alert);
// 自动关闭
const duration = options.duration || 1; //单位秒
setTimeout(() => {
this.del(id);
}, duration * 1000);
},
del (id){
for (let i = 0; i< this.alerts.length; i++) {
const element = this.alerts[i];
if(element.id === id){
this.alerts.splice(i,1);
break;
}
}
}
},
}
</script>
<style scoped>
.alert {
position: fixed;
width: 100%;
top: 30px;
left: 0;
text-align: center;
}
.alert .alert-content {
display: inline-block;
padding: 8px;
background: #fff;
margin-bottom: 10px;
}
</style>
自定义组件的挂载 这里用了两种不同的形式,考虑到不同的组件需要特定的方法,比如notice组件只能是一个单例的模式,所以用了一个notice.js给他挂载,其他通用的组件可以采用第二种方式进行挂载。
1 将notice挂载到vue实例上,第一种方式
import Notice from '@/components/Notice.vue';
import Vue from 'vue';
// 给Notice 添加一个创建组建实例的方法,可以动态编译自身模版并挂载
Notice.getInstance = props =>{
// 创建一个Vue实例
const instance = new Vue({
render(h){ //渲染函数,用户渲染置顶模版为虚拟DOM
//
return h(Notice,{ props })
}
}).$mount(); //执行挂载 ,若不置顶选择器,则模版将被渲染为文档之外的 元素
// 必须使用原生的DOM操作 插入到文档中
document.body.appendChild(instance.$el);
//获取Notice实例
const notice = instance.$children[0];
return notice;
}
// 设计一个单例模式,全局范围唯一创建一个Notice实例
let msgInstance = null;
function getInstance() {
msgInstance = msgInstance || Notice.getInstance();
return msgInstance;
}
// 暴露接口
export default{
info({duration=2,content= ''}){
getInstance().add({
content,
duration
});
}
}
第二种方式 是通用的组件挂载方式 类似与cube-ui自定义组件的方式
import Vue from 'vue';
// 给Notice 添加一个创建组建实例的方法,可以动态编译自身模版并挂载
function create(Component,props) {
// 创建一个Vue实例
const instance = new Vue({
render(h){ //渲染函数,用户渲染置顶模版为虚拟DOM
// 例 <BallAnim :el="el">
return h(Component,{ props })
}
}).$mount(); //执行挂载 ,若不置顶选择器,则模版将被渲染为文档之外的 元素
// 必须使用原生的DOM操作 插入到文档中
document.body.appendChild(instance.$el);
//获取Notice实例
const comp = instance.$children[0];
comp.remove = () => {
instance.$destory(); //销毁实例,释放内存
}
return comp;
}
// 暴露接口
export default create;
在main.js调用
import Notice from '@/components/Notice.vue';
import notice from '@/services/notice.js';
Vue.prototype.$notice = notice;
最后就是在使用这个弹窗组件
// 自定义的方式
this.$notice.info({
duration:3,
content:'消息'
})
只需要在需要的地方调用这个方法就可以。
另外一种的调用方法
在你需要的组件中 引入 create.js
import create from '@/services/create';
import BallAnim from '@/components/ballAnim.vue'; //自己创建的组件
//创建实例,并调用
const anim = create(BallAnim,{el});
//组件内自己的方法
anim.start();
anim.$on('transtioned', ()=>{
anim.remove()
})