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

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

引言

最近在实现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=#normal msgType='normal'
href=#success msgType='success'
href=#warning msgType='warning'
href=#error msgType='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 的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue自定义插件封装,实现简易的elementUi的Message和MessageBox的示例

    这次封装基于vuecli3 + typescript实现,javascript也是同理,没有区别: 自定义插件有助于我们可以将一些页面交互封装并在js或ts文件中引入实现,而不是只在 .vue文件. 1.实现toast插件封装(类似简易版的elementUi的message) 先书写一个toast组件 <template> <div ref="toastRef" class="toastMessageBox">{{ message }}<

  • Vue.extend实现组件库message组件示例详解

    目录 概述 Vue.extend message 组件配置对象(就是.vue文件) message 生成组件的函数 使用方法 效果图 总结 概述 当我们使用组件库的时候,某些组件并不是直接放到模板当中进行使用,而是通过api的方式调用生成组件并且挂在到我们的页面中,其中最常见的就是message组件,我们在组件库中看到的多数都是api调用的方式生成.记录自己基本实现message组件. Vue.extend 在vue中,要实现通过api方式实现组件的使用,这个aip是必不可少的,因此我们先了解下

  • 使用window.postMessage()方法在两个网页间传递数据

    目录 说明 发送端 postMessage程序 发送消息的基本语法: targetWindow message targetOrigin transfer 接收端 完整程序 发送程序 接收程序 说明 window.postMessage()方法可以安全地实现Window对象之间的跨域通信.例如,在一个页面和它生成的弹出窗口之间,或者是页面和嵌入其中的iframe之间. 通常情况下,不同页面上的脚本允许彼此访问,当且仅当它们源自的页面共享相同的协议,端口号和主机(也称为“同源策略”).window

  • vue中el-message的封装使用

    目录 前言 实现方法 方法一 方法二 方法三(有残缺的方法,可以带着问题看方法4) 方法四 方法五 最后 前言 最近对项目进行改造,发现在el-message使用中,如果遇到服务器挂了或者在重启等其他情况,页面message会弹出一大堆报错信息,看起来很不美观,所以对el-message进行重写改造,这里记录下改造中遇到的问题和实现,希望能对你有点帮助. 实现方法 实现方法有很多种,可以根据你实际项目情况决定使用哪一种. 方法一 直接css里面给这个样式,简单省事,但是这样子有一个问题所有的me

  • 仿照Element-ui实现一个简易的$message方法

    前言 在需要对用户进行提示时,有时会遇到这种场景:使用模态框提示太过硬核,使用toast提示又太轻了,这时候可以选择使用页面顶部滑下的消息提示.本文仿照element-ui的实现一个类似$message的方法. 思路梳理 首先我们来看下element-ui中消息提示的效果是怎么样的,找些思路. 从图中我们可以看消息提示是可以同时显示多条的,并且定位看起来都是fixed,居中展示,我们自然可以想到使用数组来存储这些消息的信息,并且根据每一条提示消息的显示隐藏更改每一项的top值,然后就是加一些动画

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

    目录 引言 支持的功能 使用方法 实现过程 如何实现不同类型的切换? 如何实现Message的弹出和消失? 如何实现往下排列而非堆叠? 如何实现添加和移除.message-active类? 如何将隐藏的Message从DOM树中移除 如何区分不同的Message? 最后的一个小细节 引言 最近在实现Message组件,就是会从屏幕顶端弹出的一个小提醒,过一会儿就消失了.我个人非常喜欢这个设计,感觉在后续的复用性也很高,于是就打算自己手写一个作为发财UI的组件 支持的功能 目前的Message有四

  • vue3.2自定义弹窗组件结合函数式调用示例详解

    目录 前言 手写弹窗组件 组件调用 函数式调用 如何使用 含样式完整源码 效果图 前言 涉及的vue3知识点/API,createApp defineProps defineEmits <script setup> v-model <script setup> 就是 setup 语法糖 defineProps 和 props 用法差不多 defineEmits 声明可向其父组件触发的事件 手写弹窗组件 很简单的弹窗组件,支持设置标题 <script setup> def

  • Vue transx组件切换动画库示例详解

    目录 来个介绍 安装 使用 支持参数 支持事件 支持API 支持的动画类型 说明 来个介绍 先奉上组件库的名称:transx github地址:github.com/tnfe/transx npm参考: www.npmjs.com/package/tra… 示例地址:codesanbox 安装 npm install transx or yarn add transx 使用 <!-- 包裹动画元素 --> <trans-x :time="time" :delay=&q

  • Ant Design 组件库按钮实现示例详解

    目录 1 antd 之 Button API 2 antd 之 Button 示例 1 antd 之 Button API antd 组件库是基于 Ant Design 设计体系的 React UI 组件库,antd 为 Web 应用提供了丰富的基础 UI 组件,可以用于研发企业级中后台产品.这篇咱们介绍 antd 组件库之 按钮. 按钮 Button 是一个比较基础的 UI 组件,一般在有交互的应用中都会用到. 其 DOM 节点为 <Button>...</Button>,ant

  • Vue业务组件封装Table表格示例详解

    目录 前言 Table组件介绍 Table组件封装思路 了解element Table组件代码 Table组件如何去封装 新建LTable组件 配置文件 配置插槽 动态组件 解决插槽存在的问题 代码实现 总结 前言 这个系列主要是分享自己在工作中常用到的业务组件,以及如何对这些组件进行有效的封装和封装的思路.注:都是基于element ui进行二次封装. 封装组件的基本方法就是通过props和emit进行父子组件的传值和通信.利用插槽.组件等去增加组件的可扩展性和复用性. Table组件介绍 用

  • Vue组件的继承用法示例详解

    目录 Vue组件的继承用法 Vue组件的继承用法 vue组件的继承适用于UI几乎一样,只是数据不一样的情况下,但是这种情况通过统一封装组件也是能实现的,小功能建议用封装,大功能建议用组件继承,因为大功能在结合搜参数的需要多重的判断,这样会导致封装的组件比较繁杂,出现过多的判断,用继承可以改写基类中的方法和数据 基类案例: <template> <div class="hello"> 父类:{{name}} <span>{{title}}</sp

  • JS前端画布与组件元信息数据流示例详解

    目录 正文 拓展应用状态与静态方法 总结 正文 接下来需要解决两个问题: 可视化搭建的其他业务元素如何与画布交互.比如拓展属性配置面板.图层列表.拖拽添加组件.定位锚点.主题等等. runtimeProps 如何访问到当前组件实例的 props. 这两个问题非常重要,而恰好又可以通过良好的数据流设计一次性解决,接下来让我们分别分析讨论一下. 问题一:可视化搭建的其他业务元素如何与画布交互.比如拓展属性配置面板.图层列表.拖拽添加组件.定位锚点.主题等等 需要设计一个 Hooks API,可以访问

  • vue 内置组件 component 的用法示例详解

    目录 component is 内置组件切换方法一: component is 内置组件切换方法二: component is 内置组件切换方法一: component组件(单独拿出一个组件来专门进行切换使用) 使用is来绑定你的组件:如下面的reviewedPlan planDetailsList attachmentList等引入的组件名 changeViewFun 是用来切换组件的方法 通过给is绑定的currentView来实现切换组件 pathUrl就是当前的路由 <template>

  • 无UI 组件Headless框架逻辑原理用法示例详解

    目录 概述 精读 总结 概述 Headless 组件即无 UI 组件,框架仅提供逻辑,UI 交给业务实现.这样带来的好处是业务有极大的 UI 自定义空间,而对框架来说,只考虑逻辑可以让自己更轻松的覆盖更多场景,满足更多开发者不同的诉求. 我们以 headlessui-tabs 为例看看它的用法,并读一读 源码. headless tabs 最简单的用法如下: import { Tab } from "@headlessui/react"; function MyTabs() { ret

随机推荐