What is the specific element you are referring to in this context?

2026-04-27 20:011阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1883个文字,预计阅读时间需要8分钟。

What is the specific element you are referring to in this context?

目录 + 需求背景 + 问题分析 + MessageBox 类的实现 + 查看showNextMsg方法的实现 + DEMO演示 + 需求背景 + 有一个需求,使用element-ui中的$alert方法提示 + 用户信息,不能一次性提示,只能一条一条地提示。

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

    需求背景

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

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

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

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

    What is the specific element you are referring to in this context?

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

    问题分析

    那我们本着弄清楚事实的心态来搞清楚问题发生的原因,那就翻一翻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="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="cdn.jsdelivr.net/npm/vue@2.7.10"></script> <script src="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消息提示的资料请关注易盾网络其它相关文章!

    本文共计1883个文字,预计阅读时间需要8分钟。

    What is the specific element you are referring to in this context?

    目录 + 需求背景 + 问题分析 + MessageBox 类的实现 + 查看showNextMsg方法的实现 + DEMO演示 + 需求背景 + 有一个需求,使用element-ui中的$alert方法提示 + 用户信息,不能一次性提示,只能一条一条地提示。

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

      需求背景

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

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

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

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

      What is the specific element you are referring to in this context?

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

      问题分析

      那我们本着弄清楚事实的心态来搞清楚问题发生的原因,那就翻一翻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="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="cdn.jsdelivr.net/npm/vue@2.7.10"></script> <script src="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消息提示的资料请关注易盾网络其它相关文章!