如下图所示,在开发项目时经常遇到需要消息弹窗、确认弹窗等功能的业务,此类组件通常都是通过js调用,然而有时我们需要实现具有特定UI风格的此类组件,但有时对原有组件修改较为繁琐,往往会选择自行封装符合要求的组件。为了使用的便捷性,又想实现自定义组件可以像第三方组件一样实现通过js进行调用,那该如何做呢?下面让我们简单研究一下吧。
第一步,使用vue+antdesign实现一个二次确认组件Confirm.vue,如下:
<!-- 二次确认弹窗 -->
<template>
<a-modal
:visible="visible"
:closable="false"
centered
:title="title"
:width="width"
>
<!-- 弹窗body -->
<slot>
<div v-html="content"></div>
</slot>
<!-- 弹窗footer -->
<template slot="footer">
<a-button v-if="sureBtnText" type="primary" @click="ok">
{{ sureBtnText }}
</a-button>
<a-button v-if="cancelBtnText" type="default" @click="cancel">
{{ cancelBtnText }}
</a-button>
</template>
</a-modal>
</template>
<script>
import { Modal } from 'ant-design-vue'
export default {
name: 'Confirm',
props: {
...Modal.props,
visible: {
type: Boolean,
default: false
},
width: {
type: [String, Number],
default: '480px'
},
title: {
type: String,
default: '系统提示'
},
sureBtnText: {
type: String,
default: '确定'
},
cancelBtnText: {
type: String,
default: '取消'
},
content: {
type: String,
default: '提示内容'
}
},
model: {
prop: 'visible',
event: 'cancel'
},
data() {
return {}
},
methods: {
show() {
this.visible = true
},
// 确定
ok() {
this.$emit('ok', false)
},
// 取消
cancel() {
this.$emit('cancel', false)
}
}
}
</script>
<style lang="scss" scoped>
::v-deep {
.ant-modal-wrap {
z-index: 9999;
}
.ant-modal-content {
box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.15);
}
.ant-modal-header {
border-color: #f5f5f5;
padding: 32px 32px 12px 32px;
border-bottom: none;
.ant-modal-title {
height: 24px;
line-height: 24px;
font-size: 16px;
color: #333;
font-weight: $font-medium;
}
}
.ant-modal-body {
padding: 0 32px 24px 32px;
font-weight: 400;
font-size: 14px;
color: #666;
line-height: 22px;
}
.ant-modal-footer {
text-align: center;
border-top: none;
padding: 0;
padding-bottom: 24px;
overflow: hidden;
.ant-btn {
margin-right: 12px;
margin-left: 0;
&:last-of-type {
margin-right: 0;
}
}
}
}
</style>
第二步,使用vue构造器将Confirm.vue封装成可通过js调用的组件,如下:
import ConfirmVue from '@/components/Confirm'
const Confirm = {}
let zIndex = 1
Confirm.install = Vue => {
// 使用vue构造器,创建子类,将Vue组件作为Vue.extend的参数
const ConfirmInstance = Vue.extend(ConfirmVue)
let currentConfirm
const initInstance = () => {
// 实例化
currentConfirm = new ConfirmInstance()
// 挂载到body上
document.body.appendChild(currentConfirm.$mount().$el)
// 确保后面出现的弹窗位于先前一个的上层
currentConfirm.$mount().$el.style.zIndex = zIndex + 100
}
// 覆盖蚂蚁金服的确认框组件
Vue.prototype.$confirm = (options) => {
if (!currentConfirm) {
initInstance()
}
// 组件设置
options.title = options.title === undefined ? '系统提示' : options.title
options.content = options.content === undefined ? '提示内容' : options.content
options.sureBtnText = options.sureBtnText === undefined ? '确定' : options.sureBtnText
options.cancelBtnText = options.cancelBtnText === undefined ? '取消' : options.cancelBtnText
// 展示弹窗
currentConfirm.show()
// 避免多次绑定事件
currentConfirm.$off('ok')
currentConfirm.$off('cancel')
// 绑定弹窗确定事件
currentConfirm.$on('ok', () => {
options.onOk && options.onOk(false)
})
// 绑定弹窗取消事件
currentConfirm.$on('cancel', () => {
options.onCancel && options.onCancel(false)
})
Object.assign(currentConfirm, options)
return currentConfirm
}
}
export default Confirm
第三步,调用示例,如下:
this.$confirm({
title: '系统提示',
onOk: () => {
alert('确定了')
},
onCancel() {
alert('取消了')
}
})
效果如图:
最后说句题外话吧,正所谓前人栽树,后人乘凉,写程序也不例外呢!之所以会有这个知识储备,也得益于帅气的HJX同学呢!
以上内容如有纰漏或更优解,望不吝赐教~