自定義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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM