自定义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 中国大陆许可协议进行许可。

posted @   何以之  阅读(1947)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 残酷游戏 卫兰
  2. 2 明知做戏 吴雨霏
  3. 3 你,好不好? 周兴哲
  4. 4 我可以 蔡旻佑
  5. 5 云烟成雨 房东的猫
  6. 6 说散就散 JC 陈咏桐
  7. 7 我配不上你 夏天Alex
  8. 8 不再联系 夏天Alex
  9. 9 等我先说 夏天Alex
  10. 10 我知道他爱你 夏天Alex
  11. 11 多想在平庸的生活拥抱你 隔壁老樊
  12. 12 这一生关于你的风景 隔壁老樊
  13. 13 我曾 隔壁老樊
  14. 14 关于孤独我想说的话 隔壁老樊
  15. 15 过客 周思涵
  16. 16 备爱 周思涵
  17. 17 嚣张 en
  18. 18 海口 后弦
残酷游戏 - 卫兰
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 林夕

作曲 : 蔡伯南

编曲 : 雷颂德

谁能用毅力便换来感情

谁凭施舍可保得住惨胜

你有多大量 亦未敢领我的情

但就算是恶梦 拒绝苏醒

如何用玩命换来温柔

如何用玩命换来温柔

如何比她好 一样不够

谈情像奋斗 共谁在斗

没人道别亦知一早要走

其实自命受苦都只因我能离不离

其实自命受苦都只因我能离不离

看着对你爱得彷似爱情欲避不避

若能耗尽力气 去捕捉你

亦能剩下自己可挽救自己

我也知越是幻想不准想你更记得起

我也知越是幻想不准想你更记得起

我在故意去将苦涩替代寂寞滋味

用残酷游戏制造卑微

自由自在莫非惨过永远受气

对你怎么好 亦无所图

对你怎么好 亦无所图

同情分多少 都也得到

明明避过你 未凭命数

明明极易活得比死更好

我也知越是幻想不准想你更记得起

我也知越是幻想不准想你更记得起

我在故意去将苦涩替代寂寞滋味

用残酷游戏制造卑微

自由自在莫非惨过永远自欺

我也知道远处有人爱惜我

我也知道远处有人爱惜我

也知做人无求最好不过

我肯知错也是错 我想知道也做到

埋头事业便令大家好过

其实自命受苦都只因我能离不离

其实自命受苦都只因我能离不离

看着对你爱得彷似爱情欲避不避

若能耗尽力气 去捕捉你

亦明如何才可释放我伤悲

我也知越是幻想不准想你更记得起

我也知越是幻想不准想你更记得起

我在故意去将苦涩替代寂寞滋味

用残酷游戏 制造卑微

自由自在莫非惨过永远受气

若然被嫌弃 也是天理

自怜自虐自讨苦吃贵客自理