自定义alert、confirm、prompt的vue组件

2023-07-11,,

Prompt.vue组件

说明:

通过props定制定制的Prompt,可选值
mode 默认值:prompt, 其他模式:confirm、message(简单的提示,可设置提示显示时间,类似alert,有顶部进度时间条)
title 默认值:{name:'系统提示',bgColor:'white',color:'black'}
close 默认值:{bgColor:'white',hoverBgColor:'red',color:'black',hoverColor:'white'}
bottom 默认值:{bgColor:'white',color:'black'}
content 其他模式下必选,prompt模式下的默认值:{keyWord:'确认密码',bgColor:'white',color:'black'}
其他模式下的默认值:{keyWord:'展示一个弹窗',bgColor:'white',color:'black'}
buttons message模式下传入该值无效
其他模式下的默认值:[{name:'确定',callback:this.sure},{name:'取消',callback:this.cancel}]
getShow 必须传否则父组件无法控制子组件的展示
源代码:
<template>
<div class="mask" v-show="isShow">
<transition>
<div class="prompt" v-show="anim">
<div class="top">
<div class="title" :style="{background:title.bgColor,color:title.color}">{{title.name}}</div>
<div class="close"
:style="{background: close.bgColor,color: close.color}"
v-show="mode==='message'"
@click="cancel"
>×</div>
</div>
<div class="center"
:style="{
background:content.bgColor,
color:content.color,
borderBottom:mode !== 'message' ? '1px solid lightgray':'',
height:mode !== 'message' ? '110px':'155px'
}"
>
<label for="promptValue"
:style="{lineHeight:mode !== 'message' ? '88px':'134px',
textAlign:content.keyWord.length<=20?'center':'left'}"
>
<span style="display: inline-block;line-height: normal;">{{content.keyWord + (mode==='prompt'?':':'')}}</span>
<input id="promptValue" type="text" v-show="mode==='prompt'" v-model="result">
</label>
</div>
<div class="bottom" :style="{background:bottom.bgColor,color:bottom.color}" v-show="mode !== 'message'">
<button
v-for="(b,index) in buttons"
:key="index"
:class="index===0?'sureBtn':'cancelBtn'"
@click="(()=>{return [sure,cancel][index]})()"
>{{b.name}}</button>
</div>
<div class="time" v-show="mode === 'message'" :style="{width:width+'px'}"></div>
</div>
</transition>
</div>
</template> <script>
export default {
name:'Prompt',
data(){
return {
mode:'prompt',
title:{name:'系统提示',bgColor:'white',color:'black'},
close:{bgColor:'white',hoverBgColor:'red',color:'black',hoverColor:'white'},
content:{keyWord:'确认密码',bgColor:'white',color:'black'},
bottom:{bgColor:'white',color:'black'},
buttons:[{name:'确定',callback:this.sure},{name:'取消',callback:this.cancel}],
showTime:3000,
isShow:false,
width:350,
result:'',//返回值
anim:false
}
},
props:['Mode','Title','Close','Bottom','Content','Buttons','GetShow'],
methods:{
sure(){
this.anim = false;
let timer = setTimeout(()=>{
this.isShow = false;
switch (this.mode){
case 'prompt': this.buttons[1].callback(this.result);break;
case 'confirm':this.buttons[1].callback(true);break;
}
clearTimeout(timer);
},500);
},
cancel(){
this.anim = false;
let timer = setTimeout(()=>{
this.isShow = false;
switch (this.mode){
case 'prompt': this.buttons[1].callback(null);break;
case 'confirm':this.buttons[1].callback(false);break;
}
clearTimeout(timer);
},500);
},
showProcessLine(time){
this.width = 350;
let ct = 0;
let timer = setInterval(()=>{
if(ct>time){
this.cancel();
clearInterval(timer);
}
this.width-=3500/time;
ct+=10;
},10);
},
/**
* show 必选,设置弹窗是否显示
* showTime message模式下可设置,默认值:3000ms
* */
setShow(show = false,time = 3000){
this.anim = show;
if(show) this.isShow = show;
else {
let timer = setTimeout(()=>{
this.isShow = show;
clearTimeout(timer)
},500);
}
if(this.mode==='message') this.showProcessLine(time);
if(this.mode==='prompt') this.result = '';
}
},
beforeMount() {
if(this.Buttons.length>2)console.error('Buttons错误:按钮个数太多!\n\t',this.Buttons);
//初始化数据
this.mode = this.Mode? this.Mode : 'prompt';
console.log('mode:',this.mode)
this.title = getValue(this.Title,{name:'系统提示',bgColor:'white',color:'black'});
this.close = getValue(this.Close,{bgColor:'white',hoverBgColor:'red',color:'black',hoverColor:'white'});
this.bottom = getValue(this.Bottom,{bgColor:'white',color:'black'});
this.content = getValue(this.Content,{keyWord:this.mode==='prompt'?'请输入':'展示一个弹窗',bgColor:'white',color:'black'});
if(this.content.keyWord.length>6 && this.mode === 'prompt'){
console.error('\''+this.content.keyWord,'\' 错误: Content里面的keyWord太长')
}
switch (this.mode){
case 'prompt' :
case 'confirm':
this.buttons = getValue(this.Buttons,[{name:'确定',callback:this.sure},{name:'取消',callback:this.cancel}]);
// console.log(this.buttons);
break;
case 'message':
break;
default:console.error('没有\''+this.Mode+'\'这个模式:\n\tMode的可选值为prompt、confirm和message!');break;
}
this.GetShow(this.setShow);
}
};
function getValue(obj,value){
if(!obj) return value;//空对象
for (const key in value) {
//没有属性则添加
if(!obj[key]) obj[key] = value[key];
else if((typeof value[key])==='object')//如果某一项属性是对象
obj[key] = getValue(obj[key],value[key])
}
return obj;
}
</script> <style scoped>
.mask{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(107, 103, 103, 0.5);
}
.prompt{
position: absolute;
width: 350px;
height: 200px;
background: white;
box-shadow: 0 0 5px 2px gray;
border-radius: 5px;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin:auto;
}
.v-enter-active{
animation: show 0.5s ease-in-out;
}
.v-leave-active{
animation: show 0.5s reverse;
}
@keyframes show {
from{
transform: scale(0);
}
to{
transform: scale(1);
}
}
.top,.center,.bottom{
width: 100%;
box-sizing: border-box;
}
.top{
border-top-left-radius: 5px;
border-top-right-radius: 5px;
height: 40px;
line-height: 40px;
padding-left: 10px;
}
.center{
border-top:1px solid lightgray;
position: relative;
}
.bottom{
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
height: 50px;
text-align: center;
}
.title{
float: left;
width: calc(100% - 41px);
height: 100%;
border-top-left-radius: 5px;
}
.close{
float: right;
width: 40px;
height: 100%;
border-left: 1px solid lightgray;
border-top-right-radius: 5px;
cursor: pointer;
text-align: center;
line-height: 40px;
font-size: 20px;
}
.center label{
position: absolute;
width: 100%;
height: auto;
box-sizing: border-box;
padding: 10px;
top: 0;
bottom: 0;
margin: auto;
overflow: auto;
/*设置字体是等宽字体*/
font-family: monospace;
}
#promptValue{
width: 60%;
height: 25px;
border: 1px solid #b2b2b2;
outline: 1px solid #5b5b5c;
border-radius: 3px;
padding-left: 5px;
}
#promptValue:focus{
outline: 3px solid rgba(26, 115, 231, 0.55);
box-shadow: 0 0 5px 2px rgba(26, 115, 231, 0.55);
}
.sureBtn,.cancelBtn{
width:60px;
height: 30px;
border: 0;
cursor: pointer;
margin: 10px calc(25% - 30px);
border-radius: 3px;
}
.sureBtn{
color: white;
background: rgb(26, 115, 231);
outline: 3px solid rgb(26, 115, 231);
border: 1px solid rgb(26, 115, 231);
}
.cancelBtn{
background: white;
outline: 3px solid rgba(26, 115, 231, 0.82);
border: 1px solid rgba(26, 115, 231, 0.41);
}
.time{
position: absolute;
left: 0;
top: 0;
height: 3px;
background: dodgerblue;
border-radius: 5px;
}
</style>

使用示例:

<template>
<div id="app">
   <!--使用-->
<Prompt Mode="prompt"
:Buttons="[{name:'确认',callback:sure},{name:'取消',callback:cancel}]"
:GetShow="setShow"
></Prompt>
</div>
</template> <script>
//引入
import Prompt from './components/Prompt'
export default {
name: 'App',
components: {//注册
Prompt
},
methods:{
sure(result){//接收prompt模式和confirm模式下的确认的返回值 分别是输入框的值 和 true
console.log(result);
},
cancel(result){//接收prompt和confirm模式下的取消的返回值 分别是null 和 false
console.log(result);
},
setShow(show){
//通过show传参控制Prompt组件是否显示
//必选参数是是否显示Boolean 可选参数是显示时间(在message模式下有效)
this.setShow = show;
}
}
}
</script>

自定义alert、confirm、prompt的vue组件的相关教程结束。

《自定义alert、confirm、prompt的vue组件.doc》

下载本文的Word格式文档,以方便收藏与打印。