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 相关文章推荐
juqery 学习之四 筛选过滤
Nov 30 Javascript
JS操作数据库的实例代码
Oct 17 Javascript
jQuery中的$.ajax()方法应用
May 06 Javascript
JavaScript中指定函数名称的相关方法
Jun 04 Javascript
js内置对象处理_打印学生成绩单的简单实现
Sep 24 Javascript
JS中静态页面实现微信分享功能
Feb 06 Javascript
详解Node.js中exports和module.exports的区别
Apr 19 Javascript
js 两数组去除重复数值的实例
Dec 06 Javascript
写gulp遇到的ES6问题详解
Dec 03 Javascript
使用jQuery实现掷骰子游戏
Oct 24 jQuery
js消除图片小游戏代码
Dec 11 Javascript
Element-ui Layout布局(Row和Col组件)的实现
Dec 06 Vue.js
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数组函数序列之rsort() - 对数组的元素值进行降序排序
2011/11/02 PHP
smarty模板中使用get、post、request、cookies、session变量的方法
2014/04/24 PHP
学习php设计模式 php实现访问者模式(Visitor)
2015/12/07 PHP
php 生成签名及验证签名详解
2016/10/26 PHP
深入理解Yii2.0乐观锁与悲观锁的原理与使用
2017/07/26 PHP
javascript 面向对象的JavaScript类
2010/05/04 Javascript
解读JavaScript代码 var ie = !-[1,] 最短的IE判定代码
2011/05/28 Javascript
jquery仿京东导航/仿淘宝商城左侧分类导航下拉菜单效果
2013/04/24 Javascript
js的.innerHTML = &quot;&quot;IE9下显示有错误的解决方法
2013/09/16 Javascript
JS获取Table中td值的方法
2015/03/19 Javascript
JavaScript基础篇(3)之Object、Function等引用类型
2015/11/30 Javascript
详解javascript中对数据格式化的思考
2017/01/23 Javascript
基于angular-utils-ui-breadcrumbs使用心得(分享)
2017/11/03 Javascript
浅谈微信小程序之官方UI框架we-ui使用教程
2018/08/20 Javascript
vue动画打包后失效问题的解决方法
2018/09/18 Javascript
微信小程序图表插件wx-charts用法实例详解
2019/05/20 Javascript
关于layui表单中按钮自动提交的解决方法
2019/09/09 Javascript
Vue中Table组件行内右键菜单实现方法(基于 vue + AntDesign)
2019/11/21 Javascript
[02:40]2014DOTA2 国际邀请赛中国区预选赛 四大豪门抵达华西村
2014/05/23 DOTA
python中Pycharm 输出中文或打印中文乱码现象的解决办法
2017/06/16 Python
基于pip install django失败时的解决方法
2018/06/12 Python
Python干货:分享Python绘制六种可视化图表
2018/08/27 Python
python 截取XML中bndbox的坐标中的图像,另存为jpg的实例
2020/03/10 Python
浅谈matplotlib 绘制梯度下降求解过程
2020/07/12 Python
Python如何急速下载第三方库详解
2020/11/02 Python
CSS3解决移动页面上点击链接触发色块的问题
2016/06/03 HTML / CSS
Draper James官网:知名演员瑞茜·威瑟斯彭所创品牌
2017/10/25 全球购物
JBL美国官方商店:扬声器、耳机等
2019/12/01 全球购物
澳大利亚家居用品零售商:Harris Scarfe
2020/10/10 全球购物
如何提高JDBC的性能
2013/04/30 面试题
金融专业个人求职信
2013/09/22 职场文书
实习老师个人总结的自我评价
2013/09/28 职场文书
员工自我鉴定范文
2013/10/06 职场文书
汽车驾驶求职信
2013/10/25 职场文书
毕业自我评价范文
2013/11/17 职场文书
汉语言文学职业规划
2014/02/14 职场文书