如何在vue2.x中封装一个全局的弹框并且可以通过方法的形式调用呢?我们需要用到 Vue.extend()。
Vue.extend 属于 Vue 的全局 API,在实际业务开发中我们很少会使用到这个API,相比常用的 Vue.component 写法使用 extend 步骤会更加繁琐一些。但是在一些独立组件开发或者插件开发场景中,Vue.extend + $mount 会经常使用到。
下面我们来封装一个简单的Confirm弹框插件。
1. 我们先建个文件夹叫做confirm,里面有Confirm.vue和index.js文件。
2. 写个Confirm组件,这边只是简单实现,可以根据自身需求扩展功能
<template>
<!-- 初始状态下隐藏提示框 -->
<transition name='fade'>
<div class='cus-confirm' :class='config.customClass' v-if='isShow'>
<!-- 背景遮罩 -->
<div class='mask' @click='closeMask'></div>
<div class='confirm-box'>
<div class='title-box' v-if='config.title'>{{config.title}}</div>
<div class='content-box' v-html='config.message'></div>
<div class='btn-box'>
<div class='btn cancel' @click='handleCancel'>{{config.cancelButtonText}}</div>
<div class='btn confirm' @click='handleConfirm'>{{config.confirmButtonText}}</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: 'Alert',
data() {
return {
isShow: false,
config: {
title: '提示',
message: '',
cancelButtonText: '取消',
confirmButtonText: '确定',
customClass: '',
onConfirm: ()=> {},
onCancel: ()=> {},
},
}
},
methods: {
// 关闭弹窗
close() {
this.isShow = false;
},
closeMask() {
// this.close();
},
handleCancel() {
this.config.onCancel();
this.close();
},
handleConfirm() {
this.config.onConfirm();
this.close();
},
},
};
</script>
<style lang='less' scoped>
@btnMain: #0070ff;
@btnDark: darken(@btnMain, 5%);
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.confirm-box {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 320px;
padding: 20px 10px;
background-color: #fff;
border-radius: 6px;
box-shadow: 0 5px 8px rgba(0, 0, 0, 0.05);
z-index: 3001;
}
.title-box{
text-align: center;
font-size: 15px;
color: #000;
}
.content-box {
text-align: center;
font-size: 14px;
color: rgba(0, 0, 0, 0.85);
padding: 20px 0;
}
.btn-box{
display: flex;
align-items: center;
justify-content: center;
}
.btn {
line-height: 32px;
padding: 0 16px;
text-align: center;
border-radius: 4px;
font-size: 14px;
&.cancel {
background-color: #ededed;
color: #333;
cursor: pointer;
}
&.confirm {
background-color: @btnMain;
color: #fff;
cursor: pointer;
margin-left: 12px;
&:hover {
background-color: @btnDark;
}
}
}
.mask {
position: fixed;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
left: 0;
top: 0;
overflow: hidden;
z-index: 3000;
}
</style>
3. 通过Vue.extend方法创建子类,然后实例化挂载到div,再添加到body下面。
我这边是注册插件的时候实例化挂载了,也可以在调用弹框的方法里面再去实例化ConfirmConstructor,这样需要注意弹框关闭后的处理以及dom的移除操作。
import Confirm from './Confirm.vue';
const confirmPlugin = {
install(Vue, config) {
// 创建一个子类
const ConfirmConstructor = Vue.extend(Confirm);
// 实例化这个子类
const instance = new ConfirmConstructor();
// 创建一个div元素,并把实例挂载到div元素上
instance.$mount(document.createElement('div'));
// 将el插入到body元素中
document.body.appendChild(instance.$el);
// 添加实例方法,可自定义
Vue.prototype[config.name || '$confirm'] = (options) => {
instance.config = { ...instance.config, ...options };
instance.isShow = true;
return instance;
};
},
};
export default confirmPlugin;
4. 注册confirm插件
import Vue from 'vue'
import confirm from './modules/confirm/index.js'
Vue.use(confirm)
5. 在组件中调用弹框
this.$confirm({title: '我是title', message: '奥斯卡打开手机德哈卡生地会考静安寺', onCancel:()=> {
console.log('点击了取消');
}, onConfirm:()=> {
console.log('点击了确认')
}});
效果如下:
联系客服