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>