早前写过一篇关于vue自定义弹出询问框、输入框、提示框的贴子,当时只是实现了组件化,组件需要在各个业务模板进行引用,不能全局化使用,不太方便,本次将其改进成了全局使用,具体的业务模块不需要引入组件,直接调用main.js注册的全局方法即可。
涉及技术点:
遮罩层样式,自定义组件,子组件套用组件,子组件调用父组件方法,组件属性监听,输入框默认获得焦点,输入框数据双向绑定、组件注册
效果图如下:
询问框:
输入框:
提示框
Toast
询问框组件代码
javascript"><template>
<div v-if="show" class="mask">
<div class="dlg-msg-box flex flex-col">
<div class="flex flex-space-between full-width">
<div class="font-bold">{{caption}}</div>
<div class="pointer" @click="close"><img class="logo-22" src="@/assets/images/guanbi.png"/></div>
</div>
<div class="margin-top-l" style="height:45px;">{{msg}}</div>
<div class="flex flex-end margin-top-xl">
<div class="btn-huibai-auto pointer" style="width:80px" @click="cancelClick">取消</div>
<div class="margin-left-m btn-blue-auto pointer" style="width:80px" @click="confirmClick">确定</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'MsgBox',
props: {
caption:{},
show: {},
msg:{},
callback:{}
},
data() {
return {
}
},
methods: {
init() {
this.show = true;
},
close() {
this.show = false;
this.callback("close")
},
confirmClick() {
this.show = false;
this.callback("yes")
//this.$emit('confirm');
},
cancelClick() {
this.show = false;
this.callback("no")
}
}
}
</script>
<style>
.dlg-msg-box {
border-radius: 5px;
width: 350px;
height: 160px;
background-color: #fff;
padding: 30px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
</style>
输入框组件代码
<template>
<div v-if="show" class="mask">
<div class="dlg-input-box flex flex-col">
<div class="flex flex-space-between full-width">
<div class="font-bold">{{caption}}</div>
<div class="pointer" @click="close"><img class="logo-22" src="@/assets/images/guanbi.png"/></div>
</div>
<div class="margin-top-xl flex flex-col">
<input class="input-box" placeholder="请输入" v-model="inputValue" ref="getfocus"/>
</div>
<div class="flex flex-end margin-top-xl">
<div class="btn-huibai-auto pointer" style="width:80px" @click="cancelClick">取消</div>
<div class="margin-left-m btn-blue-auto pointer" style="width:80px" @click="confirmClick">确定</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'InputBox',
props: {
caption:{},
value:{},
show: {},
callback: {}
},
watch: {
show(val){
if (val == true) {
this.$nextTick(() => {
this.$refs.getfocus.focus();
})
}
},
value(val){
this.inputValue = val;
}
},
data() {
return {
}
},
methods: {
close() {
this.show = false;
},
init() {
this.show = true;
},
confirmClick() {
if (this.inputValue == "") {
this.$showToast({
msg: '内容未填写',
duration: 2000
})
} else {
this.callback(this.inputValue)
}
},
cancelClick() {
this.show = false;
}
}
}
</script>
<style>
.dlg-input-box {
border-radius: 5px;
width: 350px;
height: 160px;
background-color: #fff;
padding: 30px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
</style>
提示框组件代码
<template>
<div v-if="show" class="mask">
<div class="dlg-show flex flex-col">
<div class="flex flex-space-between full-width">
<div class="font-bold">{{caption}}</div>
<div class="pointer" @click="close"><img class="logo-22" src="@/assets/images/guanbi.png"/></div>
</div>
<div class="margin-top-l" style="height:45px;">{{msg}}</div>
<div class="flex flex-end margin-top-xl">
<div class="margin-left-m btn-blue-auto pointer full-width" @click="confirmClick">确定</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'MsgShow',
props: {
caption:{},
show: {},
msg:{},
callback:{}
},
data() {
return {
}
},
methods: {
init() {
this.show = true;
},
close() {
this.show = false;
},
confirmClick() {
this.show = false;
this.callback("yes");
}
}
}
</script>
<style>
.dlg-show {
border-radius: 5px;
width: 300px;
height: 140px;
background-color: #fff;
padding: 30px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
</style>
toast组件代码
<template>
<div v-if="show" class="mask" style="z-index: 99999;">
<div class="dlg-show1 flex flex-center-sp flex-center-cz">
<div>{{msg}}</div>
</div>
</div>
</template>
<script>
export default {
name: 'Toast',
props: {
show: {},
msg:{},
duration: {
type: Number,
default: 2000
}
},
data() {
return {
timerDuration: null
}
},
watch: {
show(n) {
if (!n && this.timerDuration) {
clearTimeout(this.timerDuration)
this.timerDuration = null
}
}
},
methods: {
init() {
this.show = true
this.timerDuration = setTimeout(() => {
this.show = false
}, this.duration)
},
clear() {
this.show = false
}
}
}
</script>
<style>
.dlg-show1 {
border-radius: 5px;
width: 300px;
background-color: #ffffff;
padding: 10px;
height: 30px;
position: absolute;
margin-left: auto;
margin-right: auto;
top: 20px;
left: 0;
right: 0;
bottom: 0;
}
</style>
js代码
import MsgBox from '@/***ponents/MsgBox.vue'
let ConfirmConstructor, instance
const showMsgBox = {
install(Vue) {
ConfirmConstructor = Vue.extend(MsgBox)
instance = new ConfirmConstructor().$mount()
document.body.appendChild(instance.$el)
Vue.prototype.$showMsgBox = options => {
Object.assign(instance, options)
instance.init()
}
}
}
export default showMsgBox
import InputBox from '@/***ponents/InputBox.vue'
let ConfirmConstructor, instance
const showInputBox = {
install(Vue) {
ConfirmConstructor = Vue.extend(InputBox)
instance = new ConfirmConstructor().$mount()
document.body.appendChild(instance.$el)
Vue.prototype.$showInputBox = options => {
Object.assign(instance, options)
instance.init()
}
}
}
export default showInputBox
import MsgShow from '@/***ponents/MsgShow.vue'
let ConfirmConstructor, instance
const showMsgShow = {
install(Vue) {
ConfirmConstructor = Vue.extend(MsgShow)
instance = new ConfirmConstructor().$mount()
document.body.appendChild(instance.$el)
Vue.prototype.$showMsgShow = options => {
Object.assign(instance, options)
instance.init()
}
}
}
export default showMsgShow
import Toast from '@/***ponents/Toast.vue'
let ConfirmConstructor, instance
const showToast = {
install(Vue) {
ConfirmConstructor = Vue.extend(Toast)
instance = new ConfirmConstructor().$mount()
document.body.appendChild(instance.$el)
Vue.prototype.$showToast = options => {
Object.assign(instance, options)
instance.init()
}
Vue.prototype.$showToast.clear = () => {
instance.clear()
}
}
}
export default showToast
调用代码
<template>
<div class="body">
<div class="table">
<div class="filter font-bold">vue自定义全局弹出询问框、输入框、提示框、toast</div>
<div class="padding-left-l padding-right-l">
<div class="pointer cannotselect margin-top-l margin-left-l btn-blue-full" @click="MsgBoxClick">询问框</div>
<div class="pointer cannotselect margin-top-l margin-left-l btn-blue-full" @click="InputBoxClick">输入框</div>
<div class="pointer cannotselect margin-top-l margin-left-l btn-blue-full" @click="MsgShowClick">提示框</div>
<div class="pointer cannotselect margin-top-l margin-left-l btn-blue-full" @click="ToastClick">Toast</div>
</div>
</div>
</div>
</template>
<script>
/*
名称:vue自定义全局弹出询问框、输入框、提示框、toast
功能:自定义属于自己的弹出窗,涉及到技术点:遮罩层样式,自定义组件,子组件套用组件,子组件调用父组件方法,组件属性监听,输入框默认获得焦点,输入框数据双向绑定
作者:唐赢
时间:2023-3-5
*/
export default {
name: 'Main',
data () {
return {
}
},
methods: {
MsgBoxClick() {
this.$showMsgBox({
caption:"询问",
msg: '确定要删除该条记录吗?',
callback:(data) => {
if (data == "yes") {
this.$showToast({
msg: '点了确定',
duration: 2000
})
} else {
this.$showToast({
msg: '点了取消',
duration: 2000
})
}
}
})
},
InputBoxClick() {
this.$showInputBox({
caption:"提示",
inputValue: '标题1',
callback:(data) => {
console.log("最新的值", data);
}
})
},
MsgShowClick() {
this.$showMsgShow({
caption:"提示",
msg: '操作完毕!',
callback:(data) => {
console.log(data);
}
})
},
ToastClick(){
this.$showToast({
msg: '网络错误',
duration: 2000
})
}
},
}
</script>
<!-- Add "scoped" attribute to limit CSS to this ***ponent only -->
<style scoped>
.body {
display: flex;
justify-content: center;
margin-top: 73px;
width: 100%;
}
.table {
background-color: #fff;
width: 1080px;
min-height: 800px;
box-shadow: 0px 3px 6px rgba(0, 0, 0, .1);
margin-bottom: 10px;
}
.filter {
display: flex;
height: 60px;
align-items:center;
background-color: #fff;
font-size: 18px;
justify-content: center;
border-bottom: 1px solid rgba(0, 0, 0, .2);;
}
</style>
main.js代码
// The Vue build version to load with the `import` ***mand
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import "./assets/css/base.css"
import ShowToast from './assets/js/toast'
import ShowInputBox from './assets/js/inputBox'
import ShowMsgBox from './assets/js/msgBox'
import ShowMsgShow from './assets/js/msgShow'
Vue.use(ShowToast)
Vue.use(ShowInputBox)
Vue.use(ShowMsgBox)
Vue.use(ShowMsgShow)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
***ponents: { App },
template: '<App/>'
})
操作演示地址:https://lusun.***/v/cR9piucUW1r
源码地址:https://download.csdn.***/download/gdgztt/87535048