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

 更新时间:2022年08月08日 10:29:31   作者:bald3r  
这篇文章主要为大家介绍了Message组件实现发财UI的手写示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

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

支持的功能

目前的Message有四种类型:

普通提醒 normal

成功提醒 success

警告提醒 warning

错误提醒error

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

使用方法

是不是非常简单😉

<template>
  <div>
    <button @click="popNormalMsg">打开一个普通提醒</button>
  </div>
</template>
<script lang="ts">
import {popMessage} from "../../lib/popMessage";
export default {
  name: "Message1.demo",
  components: {Button},
  setup() {
    const popNormalMsg = () => {
      popMessage({
        message: '这是一个全局显示的普通提醒',   //提醒内容
        msgType: 'normal',   //提醒类型normal success error warning
        closeDelay: '2000',  //显示的时长,以ms为单位
      })
    }
    return {popNormalMsg}
  }
}
</script>

实现过程

如何实现不同类型的切换?

其实切换类型只是切换图标而已哈哈哈

这里使用了IconPark图标库,这里使用了一个投机取巧的办法,把不同的图标命名为相应的type,可以节省一些处理的步骤

  
href=#normalmsgType='normal'
href=#successmsgType='success'
href=#warningmsgType='warning'
href=#errormsgType='error'
const typeIndicator = `<use href="#${props.msgType}" rel="external nofollow"  rel="external nofollow" ></use>`
<template>
  <div ref="msgDiv" class="rich-message">
    <svg class="iconpark-icon" v-html="typeIndicator">
      //2️⃣typeIndicator的内容会原封不动的跑到这里
    </svg>
    //3️⃣最后和svg标签一起变成type对应的图标
    <div class="rich-message-msgText">{{ message }}</div>
  </div>
</template>
<script lang="ts">
export default {
  name: "Message",
  props: {
    message: {
      type: String,
      required: true,
    },
    msgType: {
      type: String,
      default: 'normal',
    },
  },
  setup(props) {
    const typeIndicator = `<use href="#${props.msgType}" rel="external nofollow"  rel="external nofollow" ></use>`
    return {typeIndicator}
    //1️⃣接受到传来的type,然后typeIndicator会自动变为相应的图标use标签
  }
}
</script>

如何实现Message的弹出和消失?

使用了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所在的div
msgContainer.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 的资料请关注脚本之家其它相关文章!

相关文章

  • Vue编写自定义Plugin详解

    Vue编写自定义Plugin详解

    这篇文章主要介绍了Vue编写自定义Plugin详解,在Vue开发中,我们经常需要使用一些第三方库或功能性模块,Vue插件就是一种将这些库或模块集成到Vue应用中的方式,插件是Vue.js提供的一种机制,用于扩展Vue的功能,需要的朋友可以参考下
    2023-08-08
  • vue导出报表至excel表格三种方式

    vue导出报表至excel表格三种方式

    这篇文章主要给大家介绍了关于vue导出报表至excel表格的三种方式,导出报表是实际开发的常见功能,前后端都可以实现表格导出,本文介绍的是用vue实现,需要的朋友可以参考下
    2023-09-09
  • Vue中JS动画与Velocity.js的结合使用

    Vue中JS动画与Velocity.js的结合使用

    这篇文章主要介绍了Vue中JS动画与Velocity.js的结合使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-02-02
  • Element el-checkbox-group v-model不支持对象(object)解决方案

    Element el-checkbox-group v-model不支持对象(object)解决方案

    本文主要介绍了Element el-checkbox-group v-model不支持对象(object)解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Vue项目中使用WebUploader实现文件上传的方法

    Vue项目中使用WebUploader实现文件上传的方法

    WebUploader是由 Baidu WebFE(FEX) 团队开发的一个简单的以 HTML5为主 , FLASH为辅 的现代 文件上传组件 。这篇文章主要介绍了在Vue项目中使用WebUploader实现文件上传,需要的朋友可以参考下
    2019-07-07
  • 手把手教你创建vue3项目的最佳方式

    手把手教你创建vue3项目的最佳方式

    如今的Vue3已经势不可挡,当然搭建一个全新的Vue3项目也有了全新的方式,下面这篇文章主要给大家介绍了关于如何手把手教你创建vue3项目的最佳方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • VUE3使用JSON编辑器的详细图文教程

    VUE3使用JSON编辑器的详细图文教程

    最近项目中有用到json编辑器,我选用了这款vue的编辑器,看起来也是比较简洁,接下来就具体介绍一下它,下面这篇文章主要给大家介绍了关于VUE3使用JSON编辑器的详细图文教程,需要的朋友可以参考下
    2023-04-04
  • 详解Vue项目中出现Loading chunk {n} failed问题的解决方法

    详解Vue项目中出现Loading chunk {n} failed问题的解决方法

    这篇文章主要介绍了详解Vue项目中出现Loading chunk {n} failed问题的解决方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • 使用vue-infinite-scroll实现无限滚动效果

    使用vue-infinite-scroll实现无限滚动效果

    vue-infinite-scroll插件可以无限滚动实现加载更多,其作用是是当滚动条滚动到距离底部的指定高度时触发某个方法。这篇文章主要介绍了用vue-infinite-scroll实现无限滚动效果,需要的朋友可以参考下
    2018-06-06
  • Vue.js 实现tab切换并变色操作讲解

    Vue.js 实现tab切换并变色操作讲解

    这篇文章主要介绍了Vue.js 实现tab切换并变色操作讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09

最新评论