VUE2实现事件驱动弹窗示例


Posted in Javascript onOctober 21, 2017

前几天想了解vue如何写弹窗组件

有以下两种可取的写法:

1.状态管理 如果弹窗组件放在根组件,使用vuex来管理组件的show和hide。放在组件内,通过增加v-show或v-if来控制,可结合slot,定义不同需求的弹窗

2.事件管理 注册一个全局事件来打开弹窗,传入需展示的文字和相关的逻辑控制,可结合promise,实现异步

觉得对用像confirme和propmt这类弹窗,还是事件驱动的好。最好就是能使用promise回调。

于是手痒就写了一个。下面是代码。

propmt.js

import Vue from 'vue'
import promptComponent from './prompt.vue' // 引入弹窗的vue文件
const promptConstructor = Vue.extend(promptComponent); // 注册组件
let instance = new promptConstructor().$mount(''); // 获得组件的实例

document.body.appendChild(instance.$el); // 将组件的element插入到body中
const Alert = (text,okText)=>{
  if(instance.show === true) { //防止多次触发
    return;
  }
  // 为弹窗数据赋值
  instance.show = true; 
  instance.isAlert = true;
  instance.okText = okText||'确定';
  instance.message = text;
  //返回一个promise对象,并为按钮添加事件监听
  return new Promise(function(resolve,reject) {
    instance.$refs.okBtn.addEventListener('click',function() {
      instance.show = false;
      resolve(true);
    })
  })
};
const Confirm = (text,okText,cancelText)=>{
  if(instance.show === true) {
    return;
  }
  instance.show = true;
  instance.okText = okText||'确定';
  instance.cancelText = cancelText||'取消';
  instance.message = text;
  return new Promise(function(resolve,reject) {
    instance.$refs.cancelBtn.addEventListener('click',function() {
      instance.show = false;
      resolve(false);
    });
    instance.$refs.okBtn.addEventListener('click',function() {
      instance.show = false;
      resolve(true);
    })
  })
};
const Prompt = (text,okText,inputType, defaultValue)=>{
  if(instance.show === true) {
    return;
  }
  instance.show = true;
  instance.isPrompt = true;
  instance.okText = okText||'确定';
  instance.message = text;
  instance.inputType = inputType || 'text';
  instance.inputValue = defaultValue || '';
  return new Promise(function(resolve,reject) {
    instance.$refs.okBtn.addEventListener('click',function() {
      instance.show = false;
      resolve(instance.inputValue);
    })
  })
};

export {Alert,Confirm,Prompt}

prompt.vue

<style lang="less" scoped>
  .confirm-enter-active {
    transition: all .2s;
  }

  .confirm-leave-active {
    transition: opacity .2s;
  }

  .confirm-leave-to {
    opacity: 0;
  }

  .confirm-enter {
    opacity: 0;
  }

  .confirm {
    position: relative;
    font-family: PingFangSC-Regular;
    font-size: 17px;
    -webkit-user-select: none;
    user-select: none;
    // 遮罩层样式
    .masker {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, .4);
      -webkit-transition: opacity .1s linear;
      transition: opacity .1s linear;
      z-index: 100;
    }
    // 入库数据错误样式
    .box {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 72%;
      -webkit-transform: translate(-50%, -50%);
      transform: translate(-50%, -50%);
      text-align: center;
      border-radius: 12px;
      background-color: #fff;
      .message {
        height: 97px;
        line-height: 24px;
        font-family: PingFangSC-Regular;
        font-size: 17px;
        vertical-align: middle;
        color: #999;
        letter-spacing: -0.41px;
        p {
          margin: 20px auto 0 auto;
          vertical-align: middle;
        }
        &::after {
          content: '';
          height: 100%;
        }
      }
      .prompt {
        margin: 20px 0;
        width: 100%;
        p {
          margin: 5px auto;
          font-size: 17px;
          line-height: 24px;
        }
        input {
          margin: 5px auto;
          border: 1px solid #333;
          border-radius: 6px;
          width: 100px;
          height: 30px;
          font-size: 14px;
          line-height: 20px;
          text-align: center;
        }
      }
      .button-group {
        a {
          width: calc(50% - 0.5px);
          text-align: center;
          font-size: 17px;
          line-height: 43px;
          color: blue;
        }
        .max-width {
          width: 100% !important;;
        }
      }
    }
  }
</style>
<template>
  <transition name="confirm">
    <div class="confirm" v-show="show">
      <div class="masker" @touchmove.prevent>
        <div class="box">
          <div class="message" v-if="!isPrompt">
            <p>{{message}}</p>
          </div>
          <div class="prompt" v-if="isPrompt">
            <p>{{message}}</p>
            <input type="text" v-model="inputValue" v-if="inputType === 'text'" ref="inputEl">
            <input type="tel" v-model.number="inputValue" @keydown="enterCheck" v-if="inputType === 'tel'" ref="inputEl">
          </div>
          <div class="button-group clearfix bd-top">
            <a class="bd-right fl" ref="cancelBtn" v-show="!isAlert && !isPrompt">{{cancelText}}</a>
            <a class="fr" ref="okBtn" :class="{'max-width': isAlert || isPrompt}">{{okText}}</a>
          </div>
        </div>
      </div>
    </div>
  </transition>
</template>
<script type="text/ecmascript-6">
  import {mapState} from 'vuex'
  export default{
    data() {
      return {
        show: false,
        message: '请输入提示语',
        okText: '确定',
        cancelText: '取消',
        isAlert: false,
        isPrompt: false,
        inputValue: '',
        inputType: ''
      }
    },
    methods: {
      // 金额输入框校验
      enterCheck(event) {
        // 只允许输入数字,删除键,11位数字
        if (event.keyCode === 46 || event.keyCode === 8) {
          return;
        }
        if (event.keyCode < 47 || event.keyCode > 58 || event.keyCode === 190) {
          event.returnValue = false;
        }
      },
    },
    watch: {
      show(){
        if (this.show) {
          this.$nextTick(() => {
            console.log(this.$refs.inputEl);
            console.log(this.inputType);
            this.$refs.inputEl.focus();
          });
        }
      }
    }
  }
</script>

main.js

import {Alert,Prompt,Confirm} from '../lib/components/prompt/prompt.js'

Vue.prototype.Alert = function(text,okText) {
  return Alert(text,okText)
};
Vue.prototype.Confirm = function(text,okText,cancelText) {
  return Confirm(text,okText,cancelText)
};
Vue.prototype.Prompt = function(text,okText,inputType, defaultValue) {
  return Prompt(text,okText,inputType, defaultValue)
};
component.vue:

inputName() {
  this.Prompt('请输入名称','确认','text').then(res =>{
    // do something use res
  });
},

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 火狐(firefox)不显示本地图片问题解决
Jul 05 Javascript
Prototype String对象 学习
Jul 19 Javascript
JavaScript 基于原型的对象(创建、调用)
Oct 16 Javascript
检测input每次的输入是否合法遇到汉字输入就有问题
May 23 Javascript
ExtJS4 表格的嵌套 rowExpander应用
May 02 Javascript
jQuery 1.9移除了$.browser可以使用$.support来替代
Sep 03 Javascript
jQuery中next()方法用法实例
Jan 07 Javascript
超实用的JavaScript代码段 附使用方法
May 22 Javascript
使用bat打开多个cmd窗口执行gulp、node
Feb 17 Javascript
详解React Native网络请求fetch简单封装
Aug 10 Javascript
使用cookie绕过验证码登录的实现代码
Oct 12 Javascript
解决vue数组中对象属性变化页面不渲染问题
Aug 09 Javascript
vue+socket.io+express+mongodb 实现简易多房间在线群聊示例
Oct 21 #Javascript
vue使用keep-alive实现数据缓存不刷新
Oct 21 #Javascript
详解在WebStorm中添加Vue.js单文件组件的高亮及语法支持
Oct 21 #Javascript
Vue filter介绍及其使用详解
Oct 21 #Javascript
详解node nvm进行node多版本管理
Oct 21 #Javascript
JS实现瀑布流布局
Oct 21 #Javascript
js实现Tab选项卡切换效果
Jul 17 #Javascript
You might like
PHP性能优化准备篇图解PEAR安装
2011/12/05 PHP
帝国cms常用标签汇总
2015/07/06 PHP
PHP基于yii框架实现生成ICO图标
2015/11/13 PHP
CI框架中类的自动加载问题分析
2016/11/21 PHP
TNC vs BOOM BO3 第三场2.13
2021/03/10 DOTA
jQuery实现当按下回车键时绑定点击事件
2014/01/28 Javascript
jquery遍历checkbox介绍
2014/02/21 Javascript
javascript实现简单的可随机变色网页计算器示例
2016/12/30 Javascript
Angular2实现自定义双向绑定属性
2017/03/22 Javascript
使用Browserify来实现CommonJS的浏览器加载方法
2017/05/14 Javascript
JavaScript基础之流程控制语句的用法
2017/08/31 Javascript
angular2 NgModel模块的具体使用方法
2019/04/10 Javascript
解决vue组件props传值对象获取不到的问题
2019/06/06 Javascript
JavaScript的查询机制LHS和RHS解析
2019/08/16 Javascript
在react中使用vue的状态管理的方法示例
2020/05/02 Javascript
jQuery实现电梯导航模块
2020/12/22 jQuery
浅谈scrapy 的基本命令介绍
2017/06/13 Python
python获取文件真实链接的方法,针对于302返回码
2018/05/14 Python
Python学习小技巧总结
2018/06/10 Python
Python Lambda函数使用总结详解
2019/12/11 Python
flask框架自定义url转换器操作详解
2020/01/25 Python
Python统计文本词汇出现次数的实例代码
2020/02/27 Python
Python抖音快手代码舞(字符舞)的实现方法
2021/02/07 Python
基于CSS3制作立体效果导航菜单
2016/01/12 HTML / CSS
全球领先的各类汽车配件零售商:Advance Auto Parts
2016/08/26 全球购物
德国高性价比网上药店:medpex
2017/07/09 全球购物
法国设计制造的扫帚和刷子:Andrée Jardin
2018/12/06 全球购物
医药营销个人求职信范文
2014/02/07 职场文书
运动会通讯稿200字
2014/02/16 职场文书
大学四年个人自我小结
2014/03/05 职场文书
门店业绩提升方案
2014/06/08 职场文书
小学生十佳少年事迹材料
2014/08/20 职场文书
大学生学习新党章思想汇报
2014/10/25 职场文书
小学语文教学随笔
2015/08/14 职场文书
python中取整数的几种方法
2021/11/07 Python
CSS link与@import的区别和用法解析
2023/05/07 HTML / CSS