Message组件源码:

main.js

  1. import Vue from 'vue';
  2. import Main from './main.vue';
  3. import { PopupManager } from 'element-ui/src/utils/popup';
  4. import { isVNode } from 'element-ui/src/utils/vdom';
  5. let MessageConstructor = Vue.extend(Main);
  6. let instance;
  7. let instances = []; // 存放当前未close的message
  8. let seed = 1;
  9. const Message = function(options) {
  10. // 当前 Vue 实例是否运行于服务器
  11. if (Vue.prototype.$isServer) return;
  12. options = options || {};
  13. if (typeof options === 'string') {
  14. options = {
  15. message: options
  16. };
  17. }
  18. //userOnClose用来存放用户设置关闭时的回调函数, 参数为被关闭的 message 实例
  19. let userOnClose = options.onClose;
  20. let id = 'message_' + seed++;
  21. // 重写options.onClose
  22. options.onClose = function() {
  23. Message.close(id, userOnClose);
  24. };
  25. // 创建message实例,此时数据还没有挂载呢,$el 属性目前不可见,无法访问到数据和真实的dom
  26. instance = new MessageConstructor({
  27. data: options
  28. });
  29. instance.id = id;
  30. //判断instance.message是不是虚拟节点
  31. if (isVNode(instance.message)) {
  32. instance.$slots.default = [instance.message];
  33. instance.message = null;
  34. }
  35. //手动地挂载一个未挂载的实例。$mount(param)中param不存在时,模板将被渲染为文档之外的的元素,并且你必须使用原生 DOM API 把它插入文档中。
  36. instance.vm = instance.$mount();
  37. //用原生DOM API把它插入body中
  38. document.body.appendChild(instance.vm.$el);
  39. instance.vm.visible = true;
  40. instance.dom = instance.vm.$el;
  41. // css z-index层级叠加,覆盖之前已出现但还未close的message
  42. instance.dom.style.zIndex = PopupManager.nextZIndex();
  43. instances.push(instance);
  44. return instance.vm;
  45. };
  46. // 给Message增加四个直接调用的方法
  47. // 支持this.$message.success('xxx')方式调用,等同于this.$message({type: 'success',message: 'xxx'})
  48. ['success', 'warning', 'info', 'error'].forEach(type => {
  49. Message[type] = options => {
  50. if (typeof options === 'string') {
  51. options = {
  52. message: options
  53. };
  54. }
  55. options.type = type;
  56. return Message(options);
  57. };
  58. });
  59. // 组件的close方法中调用onClose再调该方法
  60. Message.close = function(id, userOnClose) {
  61. for (let i = 0, len = instances.length; i < len; i++) {
  62. if (id === instances[i].id) { // 通过id找到该message实例
  63. if (typeof userOnClose === 'function') {
  64. userOnClose(instances[i]);
  65. }
  66. instances.splice(i, 1); // 移除message实例
  67. break;
  68. }
  69. }
  70. };
  71. //关闭所有的消息提示弹窗
  72. Message.closeAll = function() {
  73. for (let i = instances.length - 1; i >= 0; i--) {
  74. instances[i].close();
  75. }
  76. };
  77. export default Message;

main.vue

  1. <template>
  2. <transition name="el-message-fade">
  3. <div
  4. :class="[
  5. 'el-message',
  6. type && !iconClass ? `el-message--${ type }` : '',
  7. center ? 'is-center' : '',
  8. showClose ? 'is-closable' : '',
  9. customClass
  10. ]"
  11. v-show="visible"
  12. @mouseenter="clearTimer"
  13. @mouseleave="startTimer"
  14. role="alert">
  15. <!--自定义图标存在时显示-->
  16. <i :class="iconClass" v-if="iconClass"></i>
  17. <!--自定义图标不存在时根据type显示图标-->
  18. <i :class="typeClass" v-else></i>
  19. <slot>
  20. <!--用户设置的message的参数为字符串时,显示字符串-->
  21. <p v-if="!dangerouslyUseHTMLString" class="el-message__content">{{ message }}</p>
  22. <!--用户设置的message的参数为VNode时,在此处显示-->
  23. <p v-else v-html="message" class="el-message__content"></p>
  24. </slot>
  25. <!--当用户设置的关闭按钮显示为true时,显示关闭图标-->
  26. <i v-if="showClose" class="el-message__closeBtn el-icon-close" @click="close"></i>
  27. </div>
  28. </transition>
  29. </template>
  30. <script type="text/babel">
  31. const typeMap = {
  32. success: 'success',
  33. info: 'info',
  34. warning: 'warning',
  35. error: 'error'
  36. };
  37. export default {
  38. data() {
  39. return {
  40. visible: false,
  41. message: '', //消息文字
  42. duration: 3000, //显示时间, 毫秒。设为 0 则不会自动关闭
  43. type: 'info',
  44. iconClass: '', //自定义图标的类名,会覆盖 type
  45. customClass: '', //自定义类名
  46. onClose: null,
  47. showClose: false, //是否显示关闭按钮
  48. closed: false, //用来判断消息提示弹窗是否关闭
  49. timer: null,
  50. dangerouslyUseHTMLString: false, //是否将 message 属性作为 HTML 片段处理
  51. center: false
  52. };
  53. },
  54. computed: {
  55. // 根据type返回对应的图标类名
  56. typeClass() {
  57. return this.type && !this.iconClass
  58. ? `el-message__icon el-icon-${ typeMap[this.type] }`
  59. : '';
  60. }
  61. },
  62. watch: {
  63. closed(newVal) {
  64. if (newVal) {
  65. this.visible = false;
  66. //transitionend事件在 CSS 完成过渡后触发。
  67. this.$el.addEventListener('transitionend', this.destroyElement);
  68. }
  69. }
  70. },
  71. methods: {
  72. destroyElement() {
  73. this.$el.removeEventListener('transitionend', this.destroyElement);
  74. //完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器。
  75. // 在vue v1.x中$destroy(true)的参数为true时,则从DOM中删除其关联的DOM元素或片段;在vue2.0中不需要加参数
  76. this.$destroy(true);
  77. this.$el.parentNode.removeChild(this.$el);
  78. },
  79. close() {
  80. this.closed = true;
  81. if (typeof this.onClose === 'function') {
  82. this.onClose(this);
  83. }
  84. },
  85. //鼠标进入消息提示弹窗时,定时器清空,弹窗一直显示
  86. clearTimer() {
  87. clearTimeout(this.timer);
  88. },
  89. // 鼠标离开消息提示弹窗时,设置定时器,弹窗在this.duration关闭
  90. startTimer() {
  91. if (this.duration > 0) {
  92. this.timer = setTimeout(() => {
  93. if (!this.closed) {
  94. this.close();
  95. }
  96. }, this.duration);
  97. }
  98. },
  99. // esc关闭消息
  100. keydown(e) {
  101. if (e.keyCode === 27) {
  102. if (!this.closed) {
  103. this.close();
  104. }
  105. }
  106. }
  107. },
  108. mounted() {
  109. this.startTimer();
  110. document.addEventListener('keydown', this.keydown);
  111. },
  112. beforeDestroy() {
  113. document.removeEventListener('keydown', this.keydown);
  114. }
  115. };
  116. </script>

element-ui Message组件源码分析整理笔记(八)的更多相关文章

  1. element-ui 组件源码分析整理笔记目录

    element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...

  2. element-ui button组件 radio组件源码分析整理笔记(一)

    Button组件 button.vue <template> <button class="el-button" @click="handleClick ...

  3. element-ui MessageBox组件源码分析整理笔记(十二)

    MessageBox组件源码,有添加部分注释 main.vue <template> <transition name="msgbox-fade"> < ...

  4. element-ui input组件源码分析整理笔记(六)

    input 输入框组件 源码: <template> <div :class="[ type === 'textarea' ? 'el-textarea' : 'el-in ...

  5. element-ui Steps步骤条组件源码分析整理笔记(九)

    Steps步骤条组件源码: steps.vue <template> <!--设置 simple 可应用简洁风格,该条件下 align-center / description / ...

  6. element-ui Rate组件源码分析整理笔记(十三)

    Rate组件源码比较简单,有添加部分注释 main.vue <template> <!--valuenow当前的评分 valuetext当前显示的文本--> <div c ...

  7. Element UI table组件源码分析

    本文章从如下图所示的最基本的table入手,分析table组件源代码.本人已经对table组件原来的源码进行削减,源码点击这里下载.本文只对重要的代码片段进行讲解,推荐下载代码把项目运行起来,跟着文章 ...

  8. element-ui inputNumber、Card 、Breadcrumb组件源码分析整理笔记(三)

    inputNumber组件 <template> <!--@dragstart.prevent禁止input中数字的拖动--> <div @dragstart.preve ...

  9. element-ui Upload 上传组件源码分析整理笔记(十四)

    简单写了部分注释,upload-dragger.vue(拖拽上传时显示此组件).upload-list.vue(已上传文件列表)源码暂未添加多少注释,等有空再补充,先记下来... index.vue ...

随机推荐

  1. vue 3D小球 loading

    <template> <div class="load"> <div class="loadEffect"> <spa ...

  2. 继承extends、super、this、方法重写overiding、final、代码块_DAY08

    1:Math类的随机数(掌握) 类名调用静态方法.  包:java.lang 类:Math 方法:public static double random(): Java.lang包下的类是不用导包就可 ...

  3. 剑指offer一之二维数组中的查找

    一.题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 二.解答方法: 方法 ...

  4. Spring4 mvc+maven 框架搭建(3)

    经过前面两个环节,spring mvc的原料已经准备好了,现在就可以正式开始搭建springmvc框架了. 首先先介绍介绍搭建的框架具有的功能: 1)集成log4j,配置好日志相关并可以打印出相关的日 ...

  5. makemigrations migrate

    教程 如何重置迁移 (图片:https://www.pexels.com/photo/sky-flying-animals-birds-1209/) Django迁移系统的开发和优化使其能够进行大量迁 ...

  6. storm_常用命令

    1)nimbus:启动nimbus守护进程        storm nimbus 2)supervisor:启动supervisor守护进程        storm supervisor 3)ui ...

  7. 使用Svn的版本号[转载]

    1. 生成一个名为autover的项目 注意项目的Properties文件夹下有一个名为AssemblyInfo.cs的文件,autover程序的版本号就写在它里面. 2. 创建模板文件 在Windo ...

  8. TCP滑动窗口

    TCP利用滑动窗口实现流量控制基本的数据单位不是数据段,而是字节 滑动窗口本质上是描述接受方(本地)的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据.如果发送方收到接受 ...

  9. linux解决病毒系列之一,删除十字符libudev.so病毒文件

    前两天被服务器商通知服务器带宽流量增加,我想了想我们服务走的内网,没有什么大的带宽占用,于是我马上登录服务器. 用top命令查看运行情况,我擦,有一个进程吃了很高的cup,于是我赶紧用kill -9 ...

  10. tomcat配置说明,配置不用访问工程名

    # 配置项目访问不用输入项目名称 # [重要]亲测 <Host>中的 appBass="" 一定不能带目录,必须为空,因为启动tomcat会启动appBass下面的所有 ...