自定义alert、confirm、prompt的vue组件
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>
本文作者:何以之
本文链接:https://www.cnblogs.com/serendipity-echo/p/15616161.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步