element-ui Message组件源码分析整理笔记(八)
程序员文章站
2022-03-08 22:31:16
Message组件源码: main.js main.vue pythod
message组件源码:
main.js
import vue from 'vue'; import main from './main.vue'; import { popupmanager } from 'element-ui/src/utils/popup'; import { isvnode } from 'element-ui/src/utils/vdom'; let messageconstructor = vue.extend(main); let instance; let instances = []; // 存放当前未close的message let seed = 1; const message = function(options) { // 当前 vue 实例是否运行于服务器 if (vue.prototype.$isserver) return; options = options || {}; if (typeof options === 'string') { options = { message: options }; } //useronclose用来存放用户设置关闭时的回调函数, 参数为被关闭的 message 实例 let useronclose = options.onclose; let id = 'message_' + seed++; // 重写options.onclose options.onclose = function() { message.close(id, useronclose); }; // 创建message实例,此时数据还没有挂载呢,$el 属性目前不可见,无法访问到数据和真实的dom instance = new messageconstructor({ data: options }); instance.id = id; //判断instance.message是不是虚拟节点 if (isvnode(instance.message)) { instance.$slots.default = [instance.message]; instance.message = null; } //手动地挂载一个未挂载的实例。$mount(param)中param不存在时,模板将被渲染为文档之外的的元素,并且你必须使用原生 dom api 把它插入文档中。 instance.vm = instance.$mount(); //用原生dom api把它插入body中 document.body.appendchild(instance.vm.$el); instance.vm.visible = true; instance.dom = instance.vm.$el; // css z-index层级叠加,覆盖之前已出现但还未close的message instance.dom.style.zindex = popupmanager.nextzindex(); instances.push(instance); return instance.vm; }; // 给message增加四个直接调用的方法 // 支持this.$message.success('xxx')方式调用,等同于this.$message({type: 'success',message: 'xxx'}) ['success', 'warning', 'info', 'error'].foreach(type => { message[type] = options => { if (typeof options === 'string') { options = { message: options }; } options.type = type; return message(options); }; }); // 组件的close方法中调用onclose再调该方法 message.close = function(id, useronclose) { for (let i = 0, len = instances.length; i < len; i++) { if (id === instances[i].id) { // 通过id找到该message实例 if (typeof useronclose === 'function') { useronclose(instances[i]); } instances.splice(i, 1); // 移除message实例 break; } } }; //关闭所有的消息提示弹窗 message.closeall = function() { for (let i = instances.length - 1; i >= 0; i--) { instances[i].close(); } }; export default message;
main.vue
<template> <transition name="el-message-fade"> <div :class="[ 'el-message', type && !iconclass ? `el-message--${ type }` : '', center ? 'is-center' : '', showclose ? 'is-closable' : '', customclass ]" v-show="visible" @mouseenter="cleartimer" @mouseleave="starttimer" role="alert"> <!--自定义图标存在时显示--> <i :class="iconclass" v-if="iconclass"></i> <!--自定义图标不存在时根据type显示图标--> <i :class="typeclass" v-else></i> <slot> <!--用户设置的message的参数为字符串时,显示字符串--> <p v-if="!dangerouslyusehtmlstring" class="el-message__content">{{ message }}</p> <!--用户设置的message的参数为vnode时,在此处显示--> <p v-else v-html="message" class="el-message__content"></p> </slot> <!--当用户设置的关闭按钮显示为true时,显示关闭图标--> <i v-if="showclose" class="el-message__closebtn el-icon-close" @click="close"></i> </div> </transition> </template> <script type="text/babel"> const typemap = { success: 'success', info: 'info', warning: 'warning', error: 'error' }; export default { data() { return { visible: false, message: '', //消息文字 duration: 3000, //显示时间, 毫秒。设为 0 则不会自动关闭 type: 'info', iconclass: '', //自定义图标的类名,会覆盖 type customclass: '', //自定义类名 onclose: null, showclose: false, //是否显示关闭按钮 closed: false, //用来判断消息提示弹窗是否关闭 timer: null, dangerouslyusehtmlstring: false, //是否将 message 属性作为 html 片段处理 center: false }; }, computed: { // 根据type返回对应的图标类名 typeclass() { return this.type && !this.iconclass ? `el-message__icon el-icon-${ typemap[this.type] }` : ''; } }, watch: { closed(newval) { if (newval) { this.visible = false; //transitionend事件在 css 完成过渡后触发。 this.$el.addeventlistener('transitionend', this.destroyelement); } } }, methods: { destroyelement() { this.$el.removeeventlistener('transitionend', this.destroyelement); //完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器。 // 在vue v1.x中$destroy(true)的参数为true时,则从dom中删除其关联的dom元素或片段;在vue2.0中不需要加参数 this.$destroy(true); this.$el.parentnode.removechild(this.$el); }, close() { this.closed = true; if (typeof this.onclose === 'function') { this.onclose(this); } }, //鼠标进入消息提示弹窗时,定时器清空,弹窗一直显示 cleartimer() { cleartimeout(this.timer); }, // 鼠标离开消息提示弹窗时,设置定时器,弹窗在this.duration关闭 starttimer() { if (this.duration > 0) { this.timer = settimeout(() => { if (!this.closed) { this.close(); } }, this.duration); } }, // esc关闭消息 keydown(e) { if (e.keycode === 27) { if (!this.closed) { this.close(); } } } }, mounted() { this.starttimer(); document.addeventlistener('keydown', this.keydown); }, beforedestroy() { document.removeeventlistener('keydown', this.keydown); } }; </script>
推荐阅读
-
element-ui Upload 上传组件源码分析整理笔记(十四)
-
element-ui Tag、Dialog组件源码分析整理笔记(五)
-
element-ui button组件 radio组件源码分析整理笔记(一)
-
element-ui Carousel 走马灯源码分析整理笔记(十一)
-
element-ui Upload 上传组件源码分析整理笔记(十四)
-
element-ui input组件源码分析整理笔记(六)
-
element-ui Steps步骤条组件源码分析整理笔记(九)
-
element-ui switch组件源码分析整理笔记(二)
-
element-ui inputNumber、Card 、Breadcrumb组件源码分析整理笔记(三)
-
element-ui Rate组件源码分析整理笔记(十三)