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 css float属性的特殊写法
Nov 13 Javascript
IE6图片加载的一个BUG解决方法
Jul 13 Javascript
javascript获取四位数字或者字母的随机数
Jan 09 Javascript
javascript中DOM复选框选择用法实例
May 14 Javascript
讲解JavaScript中for...in语句的使用方法
Jun 03 Javascript
JavaScript时间操作之年月日星期级联操作
Jan 15 Javascript
浅谈jQuery中ajaxPrefilter的应用
Aug 01 Javascript
Jquery on绑定的事件 触发多次实例代码
Dec 08 Javascript
简单实现jquery焦点图
Dec 12 Javascript
Webpack实现按需打包Lodash的几种方法详解
May 08 Javascript
微信小程序日历组件calendar详解及实例
Jun 08 Javascript
windows实现npm和cnpm安装步骤
Oct 24 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可应用于面包屑导航的迭代寻找家谱树实现方法
2015/02/02 PHP
php实现的Curl封装类Curl.class.php用法实例分析
2015/09/25 PHP
常见的四种POST 提交数据方式(小总结)
2015/10/08 PHP
thinkphp框架实现数据添加和显示功能
2016/06/29 PHP
浅析PHP反序列化中过滤函数使用不当导致的对象注入问题
2020/02/15 PHP
js操作textarea方法集合封装(兼容IE,firefox)
2011/02/22 Javascript
防止浏览器记住用户名及密码的简单实用方法
2013/04/22 Javascript
js螺旋动画效果的具体实例
2013/11/15 Javascript
js showModalDialog参数的使用详解
2014/01/07 Javascript
js限制checkbox选中个数以限制六个为例
2014/07/15 Javascript
jQuery中ajax和post处理json的不同示例对比
2014/11/02 Javascript
JavaScript SHA512&amp;SHA256加密算法详解
2015/08/11 Javascript
AngularJS上拉加载问题解决方法
2016/05/23 Javascript
JS获取地址栏参数的两种方法(简单实用)
2016/06/14 Javascript
require.js 加载 vue组件 r.js 合并压缩的实例
2016/10/14 Javascript
VueJs使用Amaze ui调整列表和内容页面
2017/11/30 Javascript
Angular实现较为复杂的表格过滤,删除功能示例
2017/12/23 Javascript
React精髓!一篇全概括小结(急速)
2019/05/23 Javascript
小程序如何构建骨架屏
2019/05/29 Javascript
vue 调用 RESTful风格接口操作
2020/08/11 Javascript
详谈Python高阶函数与函数装饰器(推荐)
2017/09/30 Python
使用Python向DataFrame中指定位置添加一列或多列的方法
2019/01/29 Python
深入了解Python iter() 方法的用法
2019/07/11 Python
如何基于python操作json文件获取内容
2019/12/24 Python
Python3 webservice接口测试代码详解
2020/06/23 Python
浅析Python 中的 WSGI 接口和 WSGI 服务的运行
2020/12/09 Python
使用HTML5 Canvas API控制字体的显示与渲染的方法
2016/03/24 HTML / CSS
如何使用canvas绘制可移动网格的示例代码
2020/12/14 HTML / CSS
如何唤起类中的一个方法
2013/11/29 面试题
迅雷Cued工作心得体会
2014/01/27 职场文书
全国道德模范事迹
2014/02/01 职场文书
房屋转让协议书
2014/04/11 职场文书
员工三分钟演讲稿
2014/08/19 职场文书
2015年招生工作总结
2015/05/04 职场文书
小人国观后感
2015/06/11 职场文书
MySQL为id选择合适的数据类型
2021/06/07 MySQL