main.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <template>
  2. <transition name="el-message-fade" @after-leave="handleAfterLeave">
  3. <div
  4. v-show="visible"
  5. :class="messageClass"
  6. :style="positionStyle"
  7. role="alert"
  8. @mouseenter="clearTimer"
  9. @mouseleave="startTimer"
  10. >
  11. <i v-if="iconClass" :class="iconClass"/>
  12. <i v-else :class="typeClass"/>
  13. <slot>
  14. <p v-if="!dangerouslyUseHTMLString" class="el-message__content">{{ message }}</p>
  15. <p v-else v-html="message" class="el-message__content"/>
  16. </slot>
  17. <i v-if="showClose" class="el-message__closeBtn el-icon-close" @click="close"/>
  18. <div v-if="badge>1" :key="'badge'+badge" class="el-message__badge">{{ badge }}</div>
  19. <div v-if="progress&&!closed" :key="'progress'+badge" class="el-message__progress" :style="progressStyle"/>
  20. </div>
  21. </transition>
  22. </template>
  23. <script>
  24. export default {
  25. data() {
  26. return {
  27. visible: false,
  28. badge: 1,//标记值,大于1时显示
  29. progress: true,//是否显示进度条
  30. pause: false,//是否暂停关闭
  31. message: '',
  32. duration: 3000,
  33. startAt: 0,//上一次开始关闭计时的时间
  34. remainTime: 0,//还剩多少毫秒关闭
  35. type: '',//默认值改为js控制
  36. iconClass: '',
  37. customClass: '',
  38. onClose: null,
  39. showClose: false,
  40. closed: false,
  41. verticalOffset: 20,
  42. timer: null,
  43. dangerouslyUseHTMLString: false,
  44. center: false
  45. }
  46. },
  47. computed: {
  48. messageClass() {
  49. return [
  50. 'el-message',
  51. this.type && !this.iconClass ? `el-message--${this.type}` : '',
  52. this.center ? 'is-center' : '',
  53. this.showClose ? 'is-closable' : '',
  54. this.customClass
  55. ]
  56. },
  57. typeClass() {
  58. return this.type && !this.iconClass
  59. ? `el-message__icon el-icon-${this.type}`
  60. : ''
  61. },
  62. positionStyle() {
  63. return {
  64. 'top': `${this.verticalOffset}px`
  65. }
  66. },
  67. progressStyle() {
  68. if (!this.progress || this.closed) return 'transform: scaleX(0)'
  69. if (this.pause) return `transform: scaleX(${this.remainTime / this.duration});animation-play-state:paused`
  70. return `animation-duration: ${this.duration}ms;animation-play-state:running`
  71. }
  72. },
  73. watch: {
  74. closed(newVal) {
  75. if (newVal) this.visible = false
  76. }
  77. },
  78. methods: {
  79. handleAfterLeave() {
  80. this.$destroy(true)
  81. this.$el.parentNode.removeChild(this.$el)
  82. },
  83. close() {
  84. this.closed = true
  85. typeof this.onClose === 'function' && this.onClose(this)
  86. },
  87. clearTimer(reset) {
  88. this.pause = true
  89. this.remainTime = reset === true ? this.duration : this.remainTime - (Date.now() - this.startAt)
  90. window.clearTimeout(this.timer)
  91. },
  92. startTimer() {
  93. if (this.duration > 0 && !this.closed) {
  94. this.pause = false
  95. this.startAt = Date.now()
  96. if (this.remainTime === 0) this.remainTime = this.duration
  97. this.timer = window.setTimeout(() => !this.closed && this.close(), this.remainTime)
  98. }
  99. }
  100. },
  101. mounted() {
  102. this.startTimer()
  103. }
  104. }
  105. </script>