原生实现极简消息通知框(自写自用的UI库?)

213 阅读3分钟

突然想用到消息弹窗,但是又不想引入 element-plus,而且感觉就一个简单的消息弹窗,样式也不难,实现起来应该也挺简单的,于是上午找了一下,找到了这么一篇文档 看了几眼后,有点“繁琐”,不想看它的js,于是用了它的样式,然后自己写了一下。

步骤

  1. 先写出静态的结构和样式,此时没有用到js
  2. 使用 js,通过 js 渲染处刚才写好的 html 即可

代码

<!-- <div id="my-msg">
  <div class="message"> <p>这是一个提示框</p> </div>
  <div class="message center"> <p>这是一个提示框</p> </div>
  <div class="message success"> <p>这是一个成功提示框</p> </div>
  <div class="message warning"> <p>这是一个警告提示框</p> </div>
  <div class="message error"> <p>这是一个错误提示框</p> </div>
</div> -->
<!-- <link rel="stylesheet" href="./tmp.css"> -->
<style>
  #my-msg {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    position: fixed;
    z-index: 99999;
    left: 50%;
    top: 10px;
    transform: translateX(-50%);
  }

  #my-msg .message {
    display: flex;
    align-items: center;
    min-width: 300px;
    padding: 8px 16px;
    overflow: hidden;
    margin-top: 20px;
    border-radius: 6px;
    background-color: #edf2fc;
    border: 1px solid #edf2fc;
    font-size: 16px;
  }

  #my-msg .message p {
    line-height: 1;
    font-size: 14px;
    color: #909399;
  }

  #my-msg .message.center {
    justify-content: center;
  }

  #my-msg .message.success {
    background-color: #e1f3d8;
    border-color: #e1f3d8;
  }

  #my-msg .message.success p {
    color: #67c23a;
  }

  #my-msg .message.error {
    background-color: #fef0f0;
    border-color: #fef0f0;
  }

  #my-msg .message.error p {
    color: #f56c6c;
  }

  #my-msg .message.warning {
    background-color: #fdfce6;
    border-color: #fdfce6;
  }

  #my-msg .message.warning p {
    color: #e6a23c;
  }
</style>

<script>
  function initMsg() {
    const id = 'my-msg'
    const msgDiv = document.createElement('div')
    msgDiv.id = id
    let time
    time = setInterval(() => {
      document.body && document.body.appendChild(msgDiv) && clearInterval(time)
    })

    window.$msg = function (message, type) {
      if (message === undefined) return
      const msg = document.createElement('div')
      const parent = document.getElementById(id)
      msg.innerHTML = `<p>${message}</p>`
      msg.classList.add('message')
      type && msg.classList.add(type)
      parent.appendChild(msg)
      setTimeout(() => {
        parent.removeChild(msg)
      }, 3000)
    }
  }

  initMsg()
  setTimeout(() => { /* 不支持立即显示 */
    $msg('提示')
    $msg('居中', 'center')
    $msg('成功提示', 'success')
    $msg('错误提示', 'error')
    $msg('警告提示', 'warning')
  }, 1000);
</script>

上面就是完整代码了,不过我的样式是使用 scss 写的:

#my-msg {
  margin    : 0;
  padding   : 0;
  box-sizing: border-box;

  position : fixed;
  z-index  : 99999;
  left     : 50%;
  transform: translateX(-50%);
  top: 10px;

  /* 消息提示框容器样式 */
  .message {
    display         : flex;
    align-items     : center;
    min-width       : 300px;
    padding         : 8px 16px;
    overflow        : hidden;
    margin-top      : 20px;
    border-radius   : 6px;
    background-color: #edf2fc;
    border          : 1px solid #edf2fc;
    font-size       : 16px;

    p {
      line-height: 1;
      font-size  : 14px;
      color      : #909399;
    }

    /* 内容居中 */
    &.center {
      justify-content: center;
    }

    /* 成功提示框样式 */
    &.success {
      background-color: #e1f3d8;
      border-color    : #e1f3d8;

      p {
        color: #67c23a;
      }
    }

    /* 错误提示框样式 */
    &.error {
      background-color: #fef0f0;
      border-color    : #fef0f0;

      p {
        color: #f56c6c;
      }
    }

    /* 警告提示框样式 */
    &.warning {
      background-color: #fdfce6;
      border-color    : #fdfce6;

      p {
        color: #e6a23c;
      }
    }
  }

}

问题

虽然实现了,但是还是写不出一个 “好看” 的代码。😫。 而且实现的是一个很简陋的,没有实现点击关闭,也没有考虑一些异常情况。。。😣😣😣


======================我是更新分割线======================


因为消失的效果太丑了,当一个元素消失时,下面的元素会直接闪现到上面,没办法像 UI 组件库那样,下面的消息框会有一个上升的过渡效果。

所以就想继续实现一下。

粗略的看了一眼 element-plus 的原码,只看懂了他们是通过算 top,然后没看下去了。

想在晚上找,但突然发现,我自己连要如何描述问题都不知道要怎么描述,搜索“让元素的消失有过渡效果”基本都是单纯的单个元素的,看不下去。

本来想着有没有一种办法,类似于“弹性盒”那样,当其中一个元素消失时,旁边的元素会自己补充上去,然后找找这个过程中变化的 style,最终直接一个 transition 解决了。但是找不到,那就只能自己实现一下了。

实现方法就简单说一下吧,因为元素的直接消失,导致下方元素瞬间移到上方,解决方法就是,让下面的元素能够“感知”到上方元素的消失。所以可以让上方元素消失时,向上偏移(transform),并且要让它的高度变小,因为当上面元素的高度变小时,是有过渡效果的,并且下方的元素能够感知到。

在线可运行代码放在 codepen 了,点击下方可在线运行:

codepen在线预览

GIF 22-7-16 18-36-15.gif (gif 图有点失真)