想仿照element-ui的消息提示,多次点次时,如何自动叠加top,如下图和代码

问题

多次点次时,如何自动叠加top,倒计时结束自动减去top

element-ui

image.png

我的效果

我的代码

alert.vue
<template>
  <transition name="fade">
    <div
      class="app-alert-container"
      :class="{ hasClose: hasClose }"
      v-if="visible"
      :style="{ top: top, left: left }"
    >
      <span
        class="container-type iconfont"
        :class="logoType(type)"
        :style="{ color: logoColor(type) }"
      ></span>
      <p class="container-content">{{ content }}</p>
      <span v-if="hasClose" class="container-close" @click="visible = false"
        >x</span
      >
    </div>
  </transition>
</template>

<script>
export default {
  name: 'Alert',
  data () {
    return {
      content: '', // 内容
      time: 5000, // 自动关闭时间
      visible: false,
      type: 'info',
      hasClose: false,
      top: '',
      left: ''
    }
  },
  mounted () {
    this.close()
  },
  methods: {
    close () {
      window.setTimeout(() => {
        this.visible = false
      }, this.time)
    }
  }
}
</script>
<style lang="less">
.app-alert-container {
  display: flex;
  align-items: center;
  max-width: 600px;
  height: 40px;
  box-sizing: border-box;
  position: fixed;
  left: 50%;
  top: 50px;
  z-index: 9999 !important;
  transform: translateX(-50%);
  background-color: #edf2fc;
  transition: opacity 0.3s, transform 0.4s;
  overflow: hidden;
  padding: 10px 20px 10px 18px;
  background: #ffffff;
  box-shadow: 0px 9px 28px 8px rgba(0, 0, 0, 0.05),
    0px 6px 16px 0px rgba(0, 0, 0, 0.08), 0px 3px 6px -4px rgba(0, 0, 0, 0.12);
  border-radius: 2px;
  &.fade-enter,
  &.fade-leave-active {
    opacity: 0;
    transform: translate(-50%, -100%);
  }
}
</style>
alert.js
import Vue from 'vue'
import Alert from './alert.vue'

const AlertComponents = Vue.extend(Alert)

Alert.install = function (options, type) {
  if (options === undefined || options === null) {
    options = {
      content: ''
    }
  } else if (typeof options === 'string' || typeof options === 'number') {
    options = {
      content: options
    }
    if (type !== undefined && options !== null) {
      options.type = type
    }
  }

  const instance = new AlertComponents({
    data: options
  }).$mount()

  document.body.appendChild(instance.$el)

  Vue.nextTick(() => {
    instance.visible = true
  })
}

export default Alert
调用方法
          this.$alert({
            type: 'err',
            content: err
          })
阅读 1.9k
2 个回答

写了个简单的demo
最简单的思路

父容器定位,高度自适应,子元素(就是单个消息框)利用块级元素自动站位的原理,不停地挤下去即可

你可以理解为为数组的push,然后之前插入的隔几秒删除

维护一个instances数组表示当前页面上存在的messages实例,当新创建一个message是都会将现有的message的offsetHeight相加以获得当前的top,当一个message关闭后把他从instances数组中删除,并将剩下的message的top全部减去他的offsetHeight,以获的正确的top

相关代码:
(累加offsetHeight)
https://github.com/ElemeFE/el...

(从instances中删除关闭的message)
https://github.com/ElemeFE/el...

(赋值top)
https://github.com/ElemeFE/el...

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题