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 添加和移除函数的通用方法
Oct 20 Javascript
javascript 正则表达式相关应介绍
Nov 27 Javascript
3分钟写出来的Jquery版checkbox全选反选功能
Oct 23 Javascript
跟我学习javascript创建对象(类)的8种方法
Nov 20 Javascript
AngularJS基础 ng-click 指令示例代码
Aug 01 Javascript
使用InstantClick.js让页面提前加载200ms
Sep 12 Javascript
BootStrap 标题设置跨行无效的解决方法
Oct 25 Javascript
Vue 兄弟组件通信的方法(不使用Vuex)
Oct 26 Javascript
浅谈js获取ModelAndView值的问题
Mar 28 Javascript
vue中如何去掉空格的方法实现
Nov 09 Javascript
node.js中对Event Loop事件循环的理解与应用实例分析
Feb 14 Javascript
如何利用JavaScript编写一个格斗小游戏
Jan 06 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中关于codeigniter的xmlrpc的类在进行数据交换时的类型问题
2011/07/03 PHP
有道搜索和IP138的IP的API接口(PHP应用)
2012/11/29 PHP
PHP基于CURL进行POST数据上传实例
2014/11/10 PHP
PHP架构及原理知识点详解
2019/12/22 PHP
javascript实现二分查找法实现代码
2007/11/12 Javascript
JQuery 获得绝对,相对位置的坐标方法
2010/02/09 Javascript
JS 获取浏览器和屏幕宽高等信息的实现思路及代码
2013/07/31 Javascript
html的DOM中document对象images集合用法实例
2015/01/21 Javascript
node.js中的forEach()是同步还是异步呢
2015/01/29 Javascript
js确认框confirm()用法实例详解
2016/01/07 Javascript
学习使用bootstrap3栅格系统
2016/04/12 Javascript
JS定义类的六种方式详解
2016/05/12 Javascript
jQuery ajaxSubmit 实现ajax提交表单局部刷新
2016/07/04 Javascript
jquery层级选择器的实现(匹配后代元素div)
2016/09/05 Javascript
在Vue中使用echarts的实例代码(3种图)
2017/07/10 Javascript
jQuery的时间datetime控件在AngularJs中的使用实例(分享)
2017/08/17 jQuery
使用ionic(选项卡栏tab) icon(图标) ionic上拉菜单(ActionSheet) 实现通讯录界面切换实例代码
2017/10/20 Javascript
JS常用的几种数组遍历方式以及性能分析对比实例详解
2018/04/11 Javascript
基于D3.js实现时钟效果
2018/07/17 Javascript
vue代码分割的实现(codesplit)
2018/11/13 Javascript
React生命周期原理与用法踩坑笔记
2020/04/28 Javascript
Python 功能和特点(新手必学)
2015/12/30 Python
Python中pygal绘制雷达图代码分享
2017/12/07 Python
Python使用requests发送POST请求实例代码
2018/01/25 Python
python使用beautifulsoup4爬取酷狗音乐代码实例
2019/12/04 Python
python db类用法说明
2020/07/07 Python
简述python&amp;pytorch 随机种子的实现
2020/10/07 Python
使用css3制作登录表单的步骤
2014/04/07 HTML / CSS
丝芙兰法国官网:SEPHORA法国
2016/09/01 全球购物
iRobot官网:改变生活的家用机器人品牌
2016/09/20 全球购物
超级英雄、电影和电视、乐队和音乐T恤:Loud Clothing
2019/09/01 全球购物
公司拓展活动方案
2014/02/13 职场文书
假如给我三天光明读书笔记
2015/06/26 职场文书
浙江省杭州市平均工资标准是多少?
2019/07/09 职场文书
Python实战之实现康威生命游戏
2021/04/26 Python
吉利入股戴姆勒后smart“长大了”
2022/04/21 数码科技