自制消息提示组件

一. VUE文件

主要是通过v-if来增加主键的功能

<template>
<div
  class="zoehis_zoeMessage"
  ref="dialog"
  :class="['customClass',closed ? 'zoehis_zoeMessage_close_animation' : 'zoehis_zoeMessage_animation']"
  :style="positionStyle"
  v-show="visible"
  @mouseenter="clearTimer"
  @mouseleave="startTimer"
>
  <i v-if="iconClass" class="zoehis_icon zoeIconfont" :class="iconClass"></i>
  <i v-else class="zoehis_icon zoeIconfont" :class="[iconTypeClass]"></i>
  <div class="zoehis_zoeMessage_message">
    <p class="zoehis_zoeMessage_message" v-html="message"></p>
  </div>
  <i v-if="showClose" class="zoehis_icon_close zoeIconfont z_wrong_normal" @click="close"></i>
</div>
</template>

<script type="text/babel">
import { isNull } from "../../../src/utils/util.js";

let iconTypeMap = {
  success: "success_icon z_right_normal",
  error: "error_icon z_wrong_normal",
  info: "info_icon jingshi",
  warn: "warn_icon jingshi"
};

export default {
  data() {
    return {
      message: "", // 消息文字
      type: "success", // 类别,success/warning/info/error
      customClass: "", // 自定义类名
      duration: 2000, // 显示时间, 毫秒。默认2000ms
      timer: null, // 内部计时器
      visible: false, // 显示消息弹窗
      closed: false, // 关闭消息弹窗
      verticalOffset: 20,// 内部默认zoeMessage距离窗口顶部的偏移量,默认为20px
      onClose: null, // 关闭时的回调函数, 参数为被关闭的 zoeMessage 实例
      iconType: '', // 配置提示信息图标,不配置保留原始图标样子
      iconClass: '', // 自定义图标的类名,会覆盖 type
      spacingOffset: 16, // 配置消息提示框间隔,默认为16px
      showClose: false, // 展示关闭按钮
    };
  },
  computed: {
    // 获取图标样式,支持自己混合组合
    iconTypeClass() {
      let iconType = this.type;
      if (!isNull(this.iconType) && iconTypeMap[this.iconType]) {
        iconType = this.iconType;
      }
      return iconTypeMap[iconType];
    },
    positionStyle() {
        return {
          'top': `${ this.verticalOffset }px`
        };
      }
  },
  mounted() {
    this.startTimer()
  },
  watch: {
    closed(newVal) {
      if (newVal) {
        setTimeout(() => {
          this.visible = false;
          this.handleAfterLeave()
        },500)
      }
    }
  },

  methods: {
    clearTimer() {
      clearTimeout(this.timer);
    },
    startTimer() {
      if (this.duration > 0) {
        this.timer = setTimeout(() => {
          if (!this.closed) {
            this.close()
          }
        }, this.duration);
      }
    },
    close() {
      this.closed = true;
      if (typeof this.onClose === 'function') {
        this.onClose(this);
      }
    },
    // 销毁
    handleAfterLeave() {
      this.$destroy(true);
      this.$el.parentNode.removeChild(this.$el);
    },
  },
};
</script>

二. JS文件

定义一个实例,并绑定到dom上,然后设置其参数和方法,最后导出

import Vue from 'vue';
import zoeMessageVue from './zoeMessage.vue';

const MessageConstructor = Vue.extend(zoeMessageVue);

let instance;
let instances = [];
let seed = 1;

const zoeMessage = function(options) {
  if (Vue.prototype.$isServer) return;
  options = options || {};
  if (typeof options === 'string') {
    options = {
      message: options
    };
  }
  let userOnClose = options.onClose;
  let id = 'message_' + seed++;
  options.onClose = function() {
    zoeMessage.close(id, userOnClose);
  };
  instance = new MessageConstructor({
    data: options
  });
  instance.id = id;
  instance.$mount();
  document.body.appendChild(instance.$el);
  let verticalOffset = options.offset || 20;
  // 消息超过2个时,计算新的verticalOffset
  instances.forEach(item => {
    verticalOffset += item.$el.offsetHeight + item.spacingOffset;
  });
  instance.verticalOffset = verticalOffset;
  instance.visible = true;
  instances.push(instance);
  return instance;
};

['success', 'warn', 'info', 'error'].forEach(type => {
  zoeMessage[type] = (options) => {
    return zoeMessage({
      type,
      message: options
    });
  };
});

zoeMessage.close = function(id, userOnClose) {
  let len = instances.length;
  let index = -1;
  let removedHeight, removeSpacingdHeight;
  for (let i = 0; i < len; i++) {
    if (id === instances[i].id) {
      removedHeight = instances[i].$el.offsetHeight;
      removeSpacingdHeight = instances[i].spacingOffset;
      index = i;
      if (typeof userOnClose === 'function') {
        userOnClose(instances[i]);
      }
      instances.splice(i, 1);
      break;
    }
  }
  if (len <= 1 || index === -1 || index > instances.length - 1) return;
  for (let i = index; i < len - 1; i++) {
    let dom = instances[i].$el;
    dom.style['top'] =
      parseInt(dom.style['top'], 10) - removedHeight - removeSpacingdHeight + 'px';
  }
};

// 关闭全部消息
zoeMessage.closeAll = function() {
  for (let i = instances.length - 1; i >= 0; i--) {
    instances[i].close();
  }
};
export default zoeMessage;
export { zoeMessage };

三. index.js文件

导出组件

/**
 * Created by chenzhilin on 2021/11/23.
 */
 import zoeMessage from './src/zoeMessage.js';
 export default zoeMessage;

四. scss文件

通过变量设置其各自的样式

.zoehis_zoeMessage{
    outline: none;
    position: fixed;
    top: 20px;
    left: 50%;
    margin: 0;
    z-index: 10000;
    width: max-content;
    height: max-content;
    min-width: 300px;
    max-width: 60%;
    min-height: 60px;
    max-height: 10%;
    padding: 0 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0px 0px 5px $MAINBORDERLINES;
    font-family: $FONTNORMAL;
    background-color: $MAINBG;
    transform: translateX(-50%);
    overflow: hidden;
    text-overflow:ellipsis;
    .zoehis_icon{
        font-size: 26px;
        &.success_icon{color: #21b86c;}
        &.warn_icon{color: $ERRORCOLOR;}
        &.error_icon{color: $MAINURGENT;}
        &.info_icon{color: $SCROLLBARHOVE;}
        &+.zoehis_zoeMessage_message{ padding-left: 11px;}
    }
    .zoehis_icon_close{
      font-size: 26px;
      color: $MAINBG;
      padding-left: 11px;
      text-shadow: 0px 0px 5px $MAINBORDERLINES;
      &:focus {
        color: $FONTFOCUS;
      }
      &:hover {
        color: $FONTFOCUS;
      }
    }
    .zoehis_zoeMessage_message{
        font-size: $FONTMAINS;
        color: #545454;
        word-wrap: break-word;
        word-break: break-all;
        overflow: hidden;
        text-overflow:ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 3;  //显示内容的行数;    要显示几行数字为几即可!
        -webkit-box-orient: vertical;
        &:hover {
          text-overflow:inherit;
          overflow: auto;
          white-space: pre-line;     /*合并空白符序列,但是保留换行符。*/
        }
    }
}
.zoehis_zoeMessage_animation {
  -webkit-animation: zoehis_zoeMessage_animation 500ms linear both;
	animation: zoehis_zoeMessage_animation 500ms linear both;
}
@keyframes zoehis_zoeMessage_animation {
  0% {
    opacity: 0.2;
    transform: translate(-50%, -100%);
  }
  100% {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}
.zoehis_zoeMessage_close_animation {
  -webkit-animation: zoehis_zoeMessage_close_animation 500ms linear both;
	animation: zoehis_zoeMessage_close_animation 500ms linear both;
}
@keyframes zoehis_zoeMessage_close_animation {
  0% {
    opacity: 1;
    transform: translate(-50%, 0);
  }
  100% {
    opacity: 0.3;
    transform: translate(-50%, -100%);
  }
}
.zoehis_zoeMessage_animation,
.zoehis_zoeMessage_close_animation {
  transition: top 1s cubic-bezier(0.6, 0.04, 0.98, 0.335), opacity 1s;
}
posted @ 2022-01-25 17:03  暗鸦08  阅读(75)  评论(0)    收藏  举报