element ui循环调用this.$alert 消息提示只显示最后一个

目录
  • 需求背景
  • 问题分析
    • MessageBox 类的实现
    • 查看 showNextMsg 方法的实现
  • DEMO演示

需求背景

有一个需求,使用element-ui 中的$alert 方法提示 用户几条信息,不能一次性提示。仅能一条一条的提示,提示完第一条,点击确定后如果还有待提示消息,就弹出提示第二条,以此类推,直到消耗完所有需要提示的消息结束;现在模拟复现一下这个需求的期望如下图:

那这还不简单??? 我们听完需求心中已经想好了代码怎么写了。于是我们摩拳擦掌 说干就干, 一顿 C & V 操作,于是有了下面的代码:

 showMsg(){
    for(let i = 0; i < 4; i++){
      this.$alert('show message !'+ i,'提示')
    }
 }

然后满心欢喜,胸有成竹的一运行,发现事与愿违,来看下运行的结果:

我们发现并没有按我们的预期来执行,而是直接只显示了最后提示,就结束了,那么是什么问题导致了这个问题的出现呢:

问题分析

那我们本着弄清楚事实的心态来搞清楚问题发生的原因,那就翻一翻element-ui 中 $alert 方法到底是怎么实现的?

首先找到 $alert 的入口,他的入口位于 element/blob/dev/src/index.js Line:199

Vue.prototype.$alert = MessageBox.alert;

我们看到他在Vue 的原型上扩展了 $alert 方法,方法指向了 MessageBox.alert

那我们继续跟进 MessageBox.alert Line:161 看看他到底是怎么回事?

我们截取其中的代码片段:

MessageBox.alert = (message, title, options) => {
  if (typeof title === 'object') {
    options = title;
    title = '';
  } else if (title === undefined) {
    title = '';
  }
  return MessageBox(merge({
    title: title,
    message: message,
    $type: 'alert',
    closeOnPressEscape: false,
    closeOnClickModal: false
  }, options));
};

我们看到这个方法代码比较简洁,先是对参数进行了一些处理,最后把处理后的参数merge到默认的一些参数上,返回了 MessageBox 这个方法,根据他的命名我们大概能猜到 他是一个类;

MessageBox 类的实现

const MessageBox = function(options, callback) {
  // 判断是否为服务端 ? 跳过 ...
  if (Vue.prototype.$isServer) return;
  // 对传入的options 参数进行了判断,是不是 String 或者 vNode ,然后处理参数。这里主要是 处理 title 或 message
  if (typeof options === 'string' || isVNode(options)) {
    options = {
      message: options
    };
    if (typeof arguments[1] === 'string') {
      options.title = arguments[1];
    }
  //   处理了参数 callback , 吧options.callback 赋给 callback  ...
  } else if (options.callback && !callback) {
    callback = options.callback;
  }
  // 判断是否 可以使用 Promise 对象,
  if (typeof Promise !== 'undefined') {
    // 就把参数包装到 Promise 中 push 进入 msgQueue 队列中...
    return new Promise((resolve, reject) => { // eslint-disable-line
      msgQueue.push({
        options: merge({}, defaults, MessageBox.defaults, options),
        callback: callback,
        resolve: resolve,
        reject: reject
      });
      // 执行 showNextMsg() 方法
      showNextMsg();
    });
  } else {
    // 不支持 promise 就直接 吧参数 push 进队列,再执行 showNextMsg
    msgQueue.push({
      options: merge({}, defaults, MessageBox.defaults, options),
      callback: callback
    });
    showNextMsg();
  }
};

从上面的代码中 我们知道,

  • 处理了传入的参数
  • 维护了一个 msgQueue 队列,用于存放 不同场景(是否支持Promise)下的参数
  • 都执行了showNextMsg 方法

查看 showNextMsg 方法的实现

const initInstance = () => {
  instance = new MessageBoxConstructor({
    el: document.createElement('div')
  });
  instance.callback = defaultCallback;
};
const showNextMsg = () => {
  // 首先对 instance 进行了判断,如果没有就 初始化一个,初始化的方法 在上面;由此可见,instance 是一个单例
  if (!instance) {
    initInstance();
  }
  instance.action = '';
  // 判断 instance 没有显示 或者 存在 closeTimer  的场景
  if (!instance.visible || instance.closeTimer) {
    if (msgQueue.length > 0) { // 判断了队列长度
      currentMsg = msgQueue.shift(); // 移除队列第一项,拿到参数信息
      let options = currentMsg.options; // 下面对参数一顿处理
      for (let prop in options) {
        if (options.hasOwnProperty(prop)) {// 吧参数 复制给 instance
          instance[prop] = options[prop];
        }
      }
      if (options.callback === undefined) { // 判断有没有 callback 没有就使用 默认的 callback
        instance.callback = defaultCallback;
      }
      let oldCb = instance.callback; // 从新对 callback 进行制定
      instance.callback = (action, instance) => {
        oldCb(action, instance);
        showNextMsg(); // 进行了递归调用,消耗队列
      };
      // 判断了 message 是不是 vnode  如果是 就使用默认的 slot 渲染 ....
      if (isVNode(instance.message)) {
        instance.$slots.default = [instance.message];
        instance.message = null;
      } else {
        delete instance.$slots.default;
      }
      // 继续处理 参数,如果 这些参数没设置,就全部给他设置为 true
      ['modal', 'showClose', 'closeOnClickModal', 'closeOnPressEscape', 'closeOnHashChange'].forEach(prop => {
        if (instance[prop] === undefined) {
          instance[prop] = true;
        }
      });
      // 吧这个 el 挂载到 body 上面, 此时候的 el 还是隐藏的
      document.body.appendChild(instance.$el);
      // 使用Vue 的nextTick 异步更新队列,去设置 instance 的显示
      Vue.nextTick(() => {
        instance.visible = true;
      });
    }
  }
};

到这里基本就分析完了 他使用 Vue.nextTick 异步更新队列 去设置了 instance.visible = true;

异步更新队列 默认使用了 Promise.then 微任务 去处理callback

所以 我们在循环中调用 $alert , 是在最后 微任务队列清空的时候 去设置了 instance.visible = true;

so. 我们只看到最后一条提示。

故此 我们已经基本知道了问题的原因,那我对于我们的需求就立马能想到了处理方案, 我们仅需吧 每一条消息 放到 宏任务队列中去,即可:

那我们上代码:

showMsg(){
    for(let i = 0; i < 4; i++){
      let timer = setTimeout(()=>{
        this.$alert('show message !'+ i,'提示')
        clearTimeout(timer)
        timer = null
      })
    }
}

这样就成功完成了需求所描述的功能 ...

非常的nice

DEMO演示

感受一下这个 demo 吧

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>vue 基于element-ui 实现 按钮组按需折叠功能</title>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" rel="external nofollow" >
</head>
<body>
<div id="app">
    <h2>element-ui 中 alert 实现连续提示</h2>
    <el-button @click="showMsg1">DEMO1</el-button> 单个调用,提示一次
    <hr/>
    <el-button @click="showMsg2">DEMO2</el-button> 循环4次,仅提示了最后一次
    <hr/>
    <el-button @click="showMsg3">DEMO3</el-button> 循环4次,提示了每一次
    <hr/>
    <el-button @click="showMsg4">DEMO4</el-button> 放入微任务队列,仅提示最后一次
    <hr/>
    <el-button @click="showMsg5">DEMO5</el-button> 放入宏任务队列,提示每后一次
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
new Vue({
    el: '#app',
    methods: {
        showMsg1(){
          this.$alert('show message !','提示')
        },
        showMsg2(){
            for(let i = 0; i < 4; i++){
              this.$alert('show message !'+ i,'提示')
            }
        },
        showMsg3(){
            for(let i = 0; i < 4; i++){
              let timer = setTimeout(()=>{
                this.$alert('show message !'+ i,'提示')
                clearTimeout(timer)
                timer = null
              })
            }
        },
        showMsg4(){
            for(let i = 0; i < 4; i++){
              Promise.resolve().then(()=>{
                this.$alert('show message !'+ i,'提示')
              })
            }
        },
        showMsg5(){
            for(let i = 0; i < 4; i++){
              let timer = setTimeout(()=>{
                this.$alert('show message !'+ i,'提示')
                clearTimeout(timer)
                timer = null
              })
            }
        },
    },
})
</script>
</html>

以上就是element ui循环调用this.$alert 消息提示只显示最后一个的详细内容,更多关于element ui调用this.$alert 消息提示的资料请关注我们其它相关文章!

(0)

相关推荐

  • JavaScript中常用的3种弹出提示框(alert、confirm、prompt)

    三种提示框 alert () confirm() prompt () alert () alert()方法是显示一条弹出提示消息和确认按钮的警告框. 需要注意的是 :alert()是一个阻塞的函数,如果我们不点确认按钮,后面的内容就不会加载出来. 使用方式: alert("想要提示的文本内容") 样例代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <

  • Element Alert警告的具体使用方法

    组件-警告 基本用法 <template> <el-alert title="成功提示的文案" type="success"> </el-alert> <el-alert title="消息提示的文案" type="info"> </el-alert> <el-alert title="警告提示的文案" type="warning&

  • Selenium alert 弹窗处理的示例代码

    selenium提供switch_to_alert方法:捕获弹出对话框(可以定位alert.confirm.prompt对话框) switch_to_alert()    --定位弹出对话框 text()               --获取对话框文本值 accept()             --相当于点击"确认" dismiss()            --相当于点击"取消" send_keys()          --输入值(alert和confirm没

  • JavaScript实现alert弹框效果

    本文实例为大家分享了JavaScript实现alert弹框的具体代码,供大家参考,具体内容如下 因本人水平有限,不足之处还望大家指正. 先上图: 为什么会出现这个需求?浏览器自带的alert不好用吗? 自带的alert在不同的浏览器是有差异的,而且样式也不美观,用户体验度不是很好.所以我们要自己写一个alert弹框,这样我们就可以按照我们自己的需求,把alert弹框做的美观一点. 以下是alert.js代码: var myAlert = { alertbox : function(alertCo

  • element ui循环调用this.$alert 消息提示只显示最后一个

    目录 需求背景 问题分析 MessageBox 类的实现 查看 showNextMsg 方法的实现 DEMO演示 需求背景 有一个需求,使用element-ui 中的$alert 方法提示 用户几条信息,不能一次性提示.仅能一条一条的提示,提示完第一条,点击确定后如果还有待提示消息,就弹出提示第二条,以此类推,直到消耗完所有需要提示的消息结束:现在模拟复现一下这个需求的期望如下图: 那这还不简单??? 我们听完需求心中已经想好了代码怎么写了.于是我们摩拳擦掌 说干就干, 一顿 C & V 操作,

  • vue element ui validate 主动触发错误提示操作

    elementUI使用了async-validator进行表单验证,但是当我使用下拉树(el-cascader)时,发现其不主动触发,于是我只能主动去触发,方法如下: this.$refs['form'].fields[0].validateMessage = 'error message' this.$refs['form'].fields[0].validateState = 'error' 补充知识:element-ui 打开页面触发校验问题 如果你设置了关闭弹出页就resetFields

  • 使用纯JavaScript封装一个消息提示条功能示例详解

    目录 介绍 思路&布局 操作逻辑 完整代码 介绍 一个类似Element UI.Ant-Design UI等 UI 框架的消息提示功能,方便在任何网页环境中直接调用函数使用:区别在不依赖 js 及 css 引用,而是使用纯 js 进行封装实现,代码更精简,同时保持和 UI 框架一样的视觉效果(可自行修改成自己喜欢的样式) 代码仓库 在线预览效果(点击[登录].[点击复制]按钮时触发提示效果) 思路&布局 先来写单个提示条,并实现想要的过渡效果,最后再用逻辑操作输出节点即可:这里不需要父节点

  • iOS自定义推送消息提示框

    看到标题你可能会觉得奇怪 推送消息提示框不是系统自己弹出来的吗? 为什么还要自己自定义呢? 因为项目需求是这样的:最近需要做 远程推送通知 和一个客服系统 包括店铺客服和官方客服两个模块 如果有新的消息推送的时候 如果用户当前不在客服界面的时候  要求无论是在app前台 还是app退到后台 顶部都要弹出系统的那种消息提示框 这样的需求 我们就只能自定义一个在app内 弹出消息提示框 实现步骤如下: 1.我们自定义一个view 为 STPushView 推送消息的提示框view  #import

  • 【消息提示组件】,兼容IE6/7&&FF2

    作者:yemoo 来源:WWW.AJAXBBS.NET 发布日期:2007-09-03 原文地址:http://www.ajaxbbs.net/blog/post/100/ 特别说明:这只是一个纯客户端使用的js组件,非服务端控件(如asp.net控件等),改组件只是为了美化消息提示. PS:希望大家多提有实际价值的建议或意见,如果合适我会继续做完善修改. ===================================================================   

  • Android仿QQ消息提示实现弹出式对话框

    本文在<7种形式的Android Dialog使用实例>在这篇文章的基础进行学习,具体内容如下 1.概述 android原生控件向来以丑著称(新推出的Material Design当另说),因此几乎所有的应用都会特殊定制自己的UI样式.而其中弹出式提示框的定制尤为常见,本篇我们将从模仿QQ退出提示框来看一下常见的几种自定义提示框的实现方式. 这里使用的几种弹出框实现方法概括为以下几种: 自定义Dialog 自定义PopupWindow 自定义Layout View Activity的Dialo

  • 070823更新的一个[消息提示框]组件 兼容ie7

    提示:8.23修复了ie 7显示错误的bug,请下载过的朋友重新下载.对此表示抱歉! 更新说明: 2007-08-23 11:50 1.修复了IE7.0下按钮文字错位的BUG(下载源码已经更新,请下载过的朋友重新下载). 2.修改了部分js程序代码.(弹出框的高度只在初始化时进行计算) 2007-08-23 21:30  1.完善了组件简介,原来没有写5-7三个介绍,可能有些朋友也没有注意到.这里补上! ==============================================

  • C#调用RabbitMQ实现消息队列的示例代码

    前言 我在刚接触使用中间件的时候,发现,中间件的使用并不是最难的,反而是中间件的下载,安装,配置才是最难的. 所以,这篇文章我们从头开始学习RabbitMq,真正的从头开始. 关于消息队列 其实消息队列没有那么神秘,我们这样想一下,用户访问网站,最终是要将数据以HTTP的协议的方式,通过网络传输到主机的某个端口上的. 那么,接收数据的方式是什么呢?自然是端口监听啦. 那消息队列是什么就很好解释了? 它就是端口监听,接到数据后,将数据排列起来. 那这件事,我们不用中间件能做吗? 当然能做啦,写个T

  • 通过vue.extend实现消息提示弹框的方法记录

    前提回顾 在项目开发中我们经常使用的组件注册分为两种,一个是全局注册和另一个是局部注册,假设我们的业务场景是用户在浏览注册页面时,点击页面中的注册按钮后,前端根据用户的注册信息先做一次简单的验证,并根据验证弹出一个对应消息提示弹框 我们拿到这个需求后,便开始着手准备要通过局部注册消息弹框组件的方法来实现这个场景,在通过局部注册消息弹框组件的方法解决完这个需求后,自然是沾沾自喜,紧接着又迎来了一个需求,该需求是用户在点击该注册按钮时,点击几次就要出现几次这个消息弹框,你开始犯了难,并思考难道我要在

  • 总结Vue Element UI使用中遇到的问题

    基于 vue2.0 的 element-ui 框架,使用起来还是很方便的,非常适合快速开发,但是在做自己的项目中还是会碰到这样那样的问题,有些问题官方文档并不是很详尽,以下是我在使用 element-ui 过程中一些常用的或碰到的一些问题笔记. 一.DateTimePicker 日期选择范围为当前时间以及当前时间之前 <template> <div> <el-date-picker size="small" clearable :picker-option

随机推荐