Message组件实现发财UI|Message组件实现发财UI 示例详解

目录

  • 引言
  • 支持的功能
  • 使用方法
  • 实现过程
    • 如何实现不同类型的切换?
    • 如何实现Message的弹出和消失?
    • 如何实现往下排列而非堆叠?
    • 如何实现添加和移除.message-active类?
    • 如何将隐藏的Message从DOM树中移除
    • 如何区分不同的Message?
  • 最后的一个小细节

    引言 最近在实现Message组件,就是会从屏幕顶端弹出的一个小提醒,过一会儿就消失了。我个人非常喜欢这个设计,感觉在后续的复用性也很高,于是就打算自己手写一个作为发财UI的组件

    支持的功能 目前的Message有四种类型:
    普通提醒 normal

    成功提醒 success

    警告提醒 warning

    错误提醒error

    同时还支持设置持续的时间:


    使用方法 是不是非常简单


    实现过程
    如何实现不同类型的切换?
    其实切换类型只是切换图标而已哈哈哈
    这里使用了IconPark图标库,这里使用了一个投机取巧的办法,把不同的图标命名为相应的type,可以节省一些处理的步骤
    href=https://www.it610.com/article/#normal msgType='normal'
    href=https://www.it610.com/article/#success msgType='success'
    href=https://www.it610.com/article/#warning msgType='warning'
    href=https://www.it610.com/article/#error msgType='error'
    const typeIndicator = ``



    如何实现Message的弹出和消失?
    【Message组件实现发财UI|Message组件实现发财UI 示例详解】使用了CSS的transform,实际上就是Message在初始状态下是藏在画面外的,通过添加一个.message-active的类来让它显示出来,在经过closeDelay毫秒后移除.message-active类。
    .rich-message {...transform: translateY(-100px); transition: all 250ms; &.message-active {transform: translateY(0px); opacity: 1; }}


    如何实现往下排列而非堆叠?
    为了让他们能够一个一个的排列下来而不是堆叠在一起,我想到了insertAdjacentElement()方法
    element.insertAdjacentElement(position, element);

    position有下面四种取值
    'beforebegin': 在该元素本身的前面。
    'afterbegin':只在该元素当中,在该元素第一个子孩子前面。
    'beforeend':只在该元素当中,在该元素最后一个子孩子后面。
    'afterend': 在该元素本身的后面。
    不难发现这里似乎可以使用beforeend和afterend。经过我的思考,为了保持DOM树的整洁,我采用了创建一个msgContainer的div来存放所有的Message的方法,因此我也相应的使用了beforeend
    let msgContainer = document.getElementById('msgDiv')if (msgContainer === null) {msgContainer = document.createElement('div')msgContainer.id = 'msgDiv'document.body.appendChild(msgContainer)}const div = document.createElement('div'); //这个div就是Message所在的divmsgContainer.insertAdjacentElement('beforeend', div)

    给msgContainer一个CSS样式
    #msgDiv {position: absolute; top: 0; left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; justify-content: center; }


    如何实现添加和移除.message-active类?
    如果msgDiv在创建时就带有.message-active类,那么将会闪现在页面中,所以msgDiv应该是在渲染后被添加了.message-active类,为了实现这个效果,使用了一个setTimeout()。
    同时在closeDelay之后将这个类移除。
    但是这样存在一个问题,这个msgDiv只是看不见了,依然存在于DOM树中。
    setTimeout(() => {msgDiv.classList.add('message-active')}, 0)setTimeout(() => {msgDiv.classList.remove('message-active')}, closeDelay * 1);


    如何将隐藏的Message从DOM树中移除
    在Message的淡出动画结束后移除就好了,这里使用了.ontransitionendAPI,但是还存在问题,即如果有多个Message,他们会同时消失,原因是虽然每个Message在创建时都会有一个计时器,但是在移除时却是所有的msgDiv一起移除,因此需要有区分的方法。
    setTimeout(() => {msgDiv.classList.remove('message-active')msgDiv.ontransitionend = () => {app.unmount(); div.remove(); }}, closeDelay * 1);


    如何区分不同的Message?
    在本项目中,我使用了随机生成ID的方式,如此一番就能精准的控制每个msgDiv
    function randomLetter(len) {let str = ''; for (let i = 0; i < len; i++) {str += String.fromCharCode(~~(Math.random() * 26 + 65)); }return str; }const msgId = randomLetter(~~(Math.random() * 10 + 30)) //生成了一个随机字符串const app = createApp({render() {return h(Message, {message,msgType,id: msgId,}); }}); app.mount(div); const msgDiv = document.getElementById(String(msgId))setTimeout(() => {msgDiv.classList.add('message-active')}, 0)setTimeout(() => {msgDiv.classList.remove('message-active')msgDiv.ontransitionend = () => {app.unmount(); div.remove(); }}, closeDelay * 1);


    最后的一个小细节 我们使用了一个msgContainer将所有的Message包裹的起来,从而实现顺序排列,但是在最后一个Message消失后,msgContainer会作为一个空的div仍然存在于DOM树中,这很不环保,因此在最后一个Message消失后将msgContainer也一并移除
    setTimeout(() => {msgDiv.classList.remove('message-active')msgDiv.ontransitionend = () => {app.unmount(); div.remove(); if (msgContainer.children.length === 0) {msgContainer.remove()}}}, closeDelay * 1);

    以上就是Message组件实现发财UI 示例详解的详细内容,更多关于Message组件发财UI 的资料请关注脚本之家其它相关文章!

      推荐阅读