前言:
我们在写vue项目时,弹框是非常常用的组件,并且在同一个项目中,弹框大多类似。所以我们可以抽离封装出一个通用的弹框;
因为vue3可向下兼容,所以作者这边会使用vue2的写法,vue3写法大同小异。
第一步:新建相关文件
一般来说是在src/components/dialog
下新建如下两个文件:
- index.vue:该文件是组件内容相关的,用来书写弹框组件的结构、样式、和动态逻辑;
- index.js:该文件使用虚拟节点创建组件内容,并且注册组件。
第二步:书写组件内容
index.vue组件内容如下:
- 结构 + js 代码
vue
<template>
<div class="default-message" :id="boxId">
<div class="default-message-content">
<div class="default-message-title">{{ title }}</div>
<div class="default-message-value" v-html="message"></div>
<div class="default-message-btns">
<div
class="default-message-cancle default-message-btn"
v-if="cancelBtnHtml"
@click.prevent.stop="handleCancel"
>
{{ cancelBtnHtml }}
</div>
<div
class="default-message-submit default-message-btn"
@click.prevent.stop="handleOk"
>
{{ okBtnHtml }}
</div>
</div>
</div>
</div>
</template>
<script>
import i18n from "@/i18n";
import { defineComponent } from "vue";
export default defineComponent({
name: "Dialog",
data() {
return {
i18nTitle: '',
i18nOkBtn: '',
};
},
props: {
boxId: {
type: String,
default: "",
},
// 标题
title: {
type: String,
default: "",
},
// 内容
message: {
type: String,
default: "",
},
// 确定按钮文字
okBtnHtml: {
type: String,
default: '',
},
// 取消按钮文字
cancelBtnHtml: {
type: String,
default: "",
},
// 成功回调
ok_function: {
type: Function,
},
// 失败回调
cancel_function: {
type: Function,
},
},
methods: {
handleCancel() {
this.removeModal();
this.cancel_function && this.cancel_function();
},
handleOk() {
this.removeModal();
this.ok_function && this.ok_function();
},
removeModal() {
const modelDom = document.getElementById(
"__default__container__content__"
);
if (modelDom) {
document.body.removeChild(modelDom);
}
},
},
created() {
this.i18nTitle = i18n.global.t('modal_warm_tip_title');
this.i18nOkBtn = i18n.global.t('activity_ok');
},
});
</script>
结构说明:
.default-message
使我们整个弹框的容器,一般宽高都设置为100%,这个部分会有一个半透明的背景色(覆盖页面内容,防止弹框了还能操作页面);.default-message-content
为整个弹框的内容区域,包括标题、提示信息、取消按钮、确定按钮;- 取消按钮和确定按钮支持执行传入的事件,方便我们在弹框弹出后点击按钮执行相应操作;
- 样式
less
<style lang="less" scoped>
.default-message {
position: fixed;
right: 0;
top: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
background: rgba(0, 0, 0, 0.7);
.default-message-title {
color: #333;
margin: 0;
line-height: 1.5;
font-size: 18px;
min-height: 18px;
padding-top: 20px;
text-overflow: ellipsis;
font-weight: bold;
cursor: move;
text-align: center;
}
.default-message-content {
width: 85%;
position: absolute;
top: 50%;
left: 50%;
transform: translate3d(-50%, -50%, 0);
background-color: #fff;
border-radius: 6px;
transition: all 0.2s ease-in;
color: #999;
font-size: 18px;
}
.default-message-value {
padding: 28px 18px;
text-align: center;
position: relative;
color: #999;
text-align: center;
font-size: 14px;
color: rgba(102, 102, 102, 1);
}
.default-message-btns {
// border-top: 1px solid #ddd;
display: flex;
height: 60px;
position: relative;
&:after {
position: absolute;
content: "";
display: inline-block;
left: 0;
right: 0;
top: 0;
height: 1px;
transform: scaleY(0.5);
background: #ddd;
}
.default-message-btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
padding: 0 3px;
}
.default-message-submit {
color: #26a2ff;
}
.default-message-cancle {
color: #999;
position: relative;
&:after {
position: absolute;
content: "";
display: inline-block;
top: 0;
right: 0;
bottom: 0;
width: 1px;
transform: scaleX(0.5);
background: #ddd;
}
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
</style>
第三步:注册成全局组件
js
import {createVNode, render} from 'vue';
import MessageConstructor from './index.vue';
const $dialog = function (options) {
// 已存在一个弹窗则不重复渲染
if (!document.getElementById ('__default__container__content__')) {
// 创建div
const container = document.createElement ('div');
// container.className = `__default__container__message__`;
container.id = '__default__container__content__';
//创建虚拟节点
const vm = createVNode (MessageConstructor, options);
//渲染虚拟节点
render (vm, container);
document.body.appendChild (container);
}
};
export default {
//组件注册
install (app) {
app.config.globalProperties.$dialog = $dialog;
},
};
到这里,我们的弹框组件就完成了,接下来我们来使用看看。
项目中使用弹框
使用的方法也非常简单,所见即所得。
vue
app.config.globalProperties.$dialog({
title: "弹框标题",
message: "弹框提示信息文案",
okBtnHtml: "确定",
cancelBtnHtml: "取消",
ok_function: () => {
console.log("点击弹框确定按钮处理函数");
},
cancel_function: () => {
console.log("点击弹框取消按钮处理函数");
}
});
说明:
- 标题、提示文案、以及取消和确定按钮文案,我们这边直接传入,
ok_function
是确定按钮的回调,我们可以在这里做任何点击确定后想做的事,包括发送请求和异步操作,cancel_function
同理。 - 弹框图片示例:
写在后面
这是一个比较基础的弹框组件,这边示例的代码是比较全的,对细节要求不大的小伙伴可以直接用;
背景颜色、字体、布局等这些细节,因为每个业务场景不同,大家可以根据自己的需要适当调整;
弹框是固定单位的,如果小伙伴的项目需要使用响应式大小,直接对应替换大小单位即可;
对你有帮助的话给作者点点关注吧,你的支持是我不断更新的动力!Peace and love~~