前端组件库造轮子——Message组件开发教程

news2024/10/2 1:35:17

前端组件库造轮子——Message组件开发教程

前言

本系列旨在记录前端组件库开发经验,我们的组件库项目目前已在Github开源,下面是项目的部分组件。文章会详细介绍一些造组件库轮子的技巧并且最后会给出完整的演示demo。

image.png

文章旨在总结经验,开源分享,有问题的话也希望路过的大佬指正。

组件开发流程

样式和动画

首先我们来考虑样式,对于message的调用我们下面再讲。

样式的话,无非就是实现一个这样消息弹出框,同时加上弹出时的动画,这里借助vuetransition来实现。

image.png

这些都是简单的内容,代码量很少我就直接贴在这里了。

<transition name="message-fade">
<div class="message">
  <p class="message-content"></p>
</div>
</transition>

.message {
  position: fixed;
  top: 20px;
  left: 50%;
  z-index: 50;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  padding: 15px 15px 15px 20px;
  overflow: hidden;
  background-color: #f0f9eb;
  border: 1px solid #ebeef5;
  border-radius: 5px;
  transition: opacity 0.3s, transform 0.4s, top 0.4s;
  transform: translateX(-50%);
}
.message-fade-enter-active,
.message-fade-leave-active {
  opacity: 0;
  transform: translate(-50%, -100%);
}

.message-content {
  color: #67c23a;
  font-size: 14px;
  margin: 0;
}

当然现在这个message是只有空壳一样的内容,我们需要实现的效果是,有一个message函数接口,我们可以调用这个接口后弹出这个消息框。这其实就是和其它一些组件不太一样的地方,他的实现更倾向于一个接口函数一样。

写一个函数当然不是问题,问题是怎么实现调用函数后渲染我们的消息框出来。

这里就需要了解一下vue中渲染DOM的知识点了。

h函数和render函数

vue中,很多文件的开发都是在.vue文件的,这种文件开发是分为三大块来写,可以像类似写HTML时的感觉,这也是vue的卖点之一,让新手更易于上手。

但是我们要知道,.vue实际上也是需要通过一些打包工具来编译成js代码才能执行。

h函数就是把.vue中的代码编辑成一个虚拟DOM,最终会把template解析为render函数返回虚拟DOM,这点可以在Vue Dev Tools中看到:
image.png

也就是说,h函数是负责创建虚拟DOMrender是负责把这个虚拟DOM返回出去

接口函数

通过上面的介绍,大概不难猜出这个接口函数应该如何实现了,其实就是创建一个虚拟DOM出来包裹住我们的message组件,在利用render函数渲染出来即可。

import element from "./message.vue";
import { createVNode, render } from "vue";

export default function message(options) {
  if (typeof options === "string") {
    options = {
      message: options as string,
    };
  }
  const params = {
    ...options,
  };
  
  // vue2 的写法
  // new Vue(render:() => createVNode(element)).mount();
  
  const div = document.createElement("div"); // 创建一个div
  const vnode = createVNode(element, params);  // 创建一个message组件的虚拟DOM
  render(vnode, div); // 渲染虚拟DOM
  document.body.appendChild(div.firstElementChild); // 加入到body中
}

那我们既然可以调用message接口函数了,那么在message组件中还有一些逻辑需要实现——在执行结束后关闭掉弹出来的消息框。

这里就是利用v-show控制开关消息框,用定时器回调来解决关闭,我们可以利用props接收存在时间duration,这样我们的基本功能就算完成了,但是message组件还存在很多细节可以补充。

// message.vue
<transition name="message-fade">
    <div class="message" v-show="visible">
        <p class="message-content">{{ message }}</p>
    </div>
</transition>
  
const visible = ref(false);
let timer = null;
const start = () => {
  visible.value = true;
  if (timer !== null) {
    clearTimeout(timer);
  }
  if (props.duration > 0) {
    timer = setTimeout(() => {
      visible.value = false;
    }, props.duration);
  }
};

onMounted(() => {
  start();
});

onUnmounted(() => {
  if (timer !== null) {
    clearTimeout(timer);
  }
});

回调删除节点的性能优化

在刚刚上面完成的组件中,会发现当我们多次触发了message后,哪怕duration过了,节点也依然存在在body中,这些节点只是被隐藏了,并没有随着持续时间结束后删除掉。

image.png

这样显然是不太合理的,并且操作多了会存在一些性能问题,因此我们需要在这个组件在持续时间结束后可以被删除掉。

这里我们可以在动画结束后,派发出一个destroy事件

 <transition name="message-fade" @after-leave="$emit('destroy')"> // 派发删除操作
    <div class="message" v-show="visible">
      <p class="message-content">{{ message }}</p>
    </div>
 </transition>

这个$emit('destroy')会调用我们传进来的props中的onDestroy函数

// message.ts

const div = document.createElement("div");
const vnode = createVNode(element, params);
+ vnode.props.onDestroy = () => { // 在参数props中挂载销毁函数
+    render(null, div); // 利用render移除div节点
+ };
render(vnode, div);
document.body.appendChild(div.firstElementChild);

连续多次弹出的用户体验优化

当我们连续触发多次message时,会弹出多个消息,对于这多个消息,我们不希望会重叠在一起发生覆盖的情况,我们希望的是可以像下面这样。

image.png

那我们如何实现上面的效果呢?

我们可以在props中加一个offset属性,该属性为message组件的离视屏顶部的距离。

然后我们还需要知道上个节点的距离是多少,因此我们需要把连续点出的节点都记录起来,具体来说就是用一个数组把他们存起来,数组中的值按上一节点的offset基础上加合适的距离即可。

// message.ts

+ const instances: VNode[] = [];
export default function message(options) {
  ...

+  let offset = options.offset || 20;

+  instances.forEach((vnode: VNode) => {
+    offset += vnode.el.offsetHeight + 20;
+  });

  const params = {
    ...options,
+    offset,
  };
  const div = document.createElement("div");
  const vnode = createVNode(element, params);
  vnode.props.onDestroy = () => {
    render(null, div); // render会移除dom,注意:此方法在vue2中无法使用
+   instances.pop();
  };
  render(vnode, div);
  document.body.appendChild(div.firstElementChild);
+  instances.push(vnode);
}

同时,我们需要在渲染出message组件中,加上新的offset位置。

// message.vue

<transition name="message-fade" @after-leave="$emit('destroy')">
    <div class="message" v-show="visible" :style="topStyle"> // 更改top位置
      <p class="message-content">{{ message }}</p>
    </div>
</transition>
  
const topStyle = computed(() => {
  return {
    top: `${props.offset}px`,
  };
});

演示demo

完整项目demo

结语

Message组件的核心开发功能就是上面这些,其他更多的详细功能开发可以参考Hview-ui项目源码

如果想要了解更多的组件轮子开发,或者组件库开发流程,更多详细的组件开发过程更新在GitHub项目源码,最后觉得我们项目or文章不错可以点个star,点点小手支持一下,也欢迎各路大佬为我们的开源项目添砖加瓦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/983474.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux修复软RAID

系统应该将mdadm配置成当发生RAID问题时给root用户发送邮件。需要更改/etc/mdadm/mdadm.xonf里的MALLADDR 并用/etc/init.d/mdadm reload重新加载下 查看/proc/mdstat文件 可以看到sdd1被标记F&#xff0c;说明它已经失效 从/dev/md0中移除磁盘sdd1 想要移除磁盘&#xff…

vmware workstation设置固定ip的几种方法

环境: keyvalue宿主机系统Windows11虚拟机系统Ubuntu20.04虚拟化软件vmware workstation 17 provmware workstation网络模式NAT 众所周知,vmware workstation在NAT模式下,会使用dhcp分配ip,每个ip的默认租约是半小时(1800s),最大租约时间也只有2小时(7200s),所以ip会频繁变动…

C++项目实战——基于多设计模式下的同步异步日志系统-①-项目介绍

文章目录 专栏导读项目介绍开发环境核心技术环境搭建日志系统介绍1.为什么需要日志系统2.日志系统技术实现2.1同步写日志2.2异步写日志 专栏导读 &#x1f338;作者简介&#xff1a;花想云 &#xff0c;在读本科生一枚&#xff0c;C/C领域新星创作者&#xff0c;新星计划导师&a…

mysql 锁解决的办法

可以查看锁的信息,TRX_MYSQL_THREAD_ID 为processlist的表中的会话id,用于kill select trx_id,trx_state,trx_started,trx_requested_lock_id,trx_wait_started,trx_weight,trx_mysql_thread_id,trx_query from innodb_trx 可以查看锁的模式&#xff0c;类型&#xff0c;锁的表…

安防视频监控/视频汇聚平台EasyCVR服务重启,海康SDK设备无法上线是什么原因?

TSINGSEE青犀视频监控汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。旭帆科技平台既具备传统安防视频监控…

Elasticsearch:利用向量搜索进行音乐信息检索

作者&#xff1a;Alex Salgado 欢迎来到音乐信息检索的未来&#xff0c;机器学习、向量数据库和音频数据分析融合在一起&#xff0c;带来令人兴奋的新可能性&#xff01; 如果你对音乐数据分析领域感兴趣&#xff0c;或者只是热衷于技术如何彻底改变音乐行业&#xff0c;那么本…

Pycharm创建项目时如何自动添加头部信息

1.打开PyCharm&#xff0c;选择File--Settings 2.依次选择Editor---Code Style-- File and Code Templates---Python Script 3..添加头部内容 可以根据需要添加相应的信息 #!/usr/bin/python3可用的预定义文件模板变量为&#xff1a;$ {PROJECT_NAME} - 当前项目的名称。$ {NAM…

基于减法优化SABO优化ELM(SABO-ELM)负荷预测(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

第4篇 vue的常用事件操作

一 vue常用操作案例 1.1 事件渲染 1.数据渲染的方式&#xff1a;使用插值表达式{{}}进行数据渲染 2.数据渲染的方式&#xff1a;以使用 v-bind指令&#xff0c;它的简写的形式就是一个冒号&#xff08;:&#xff09;&#xff0c;v-bind 特性被称为指令。指令带有前缀 v- 代…

Vscode中注释变成繁体的解决方法

前言 文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 代码中的注释变成繁体字了、归根到底是由于字体的编码格式造成。前…

Java Properties类

使用SpringBoot框架时&#xff0c;会使用application.properties进行一些项目配置。 下面讲讲原理。 Properties是Map接口下面的一个实现类&#xff0c;所以Properties也是一种双列集合&#xff0c;用来存储键值对。但是一般不会把它当做集合来使用。当作属性文件来使用。 读…

2023年19款最佳3D打印软件

推荐&#xff1a;使用 NSDT场景编辑器 快速搭建3D应用场景 什么是好的3D打印软件&#xff1f; 虽然我们包括一系列非常不同的3D打印软件&#xff0c;旨在满足非常不同的需求&#xff0c;但有一些关键方面可以决定3D打印机软件的成败。 广泛的工具&#xff1a;我们选择了具有多…

如何使用聊天GPT自定义说明

推荐&#xff1a;使用 NSDT场景编辑器 快速搭建3D应用场景 OpenAI ChatGPT正在席卷全球。一周又一周&#xff0c;更新不断提高您可以使用这种最先进的语言模型做什么的标准。 在这里&#xff0c;我们深入研究了OpenAI最近在ChatGPT自定义指令上发布的公告。此功能最初以测试版…

Cesium之TerrainProvider地形数据获取

1. 挖方填方的案例中是用什么方法获取的地形数据&#xff1f; 是有官方的api接口一口气返回一个区域内的高程值吗 回答&#xff1a;读取渲染的地形瓦片的三角面。 2. 你们怎么通过高程点构建三角网的&#xff1f; 回答&#xff1a;读取地形瓦片的顶点和索引 3. 这个是有现…

C++ - 多态语法 - 虚函数使用介绍

多态简单介绍 多态就是多种形态&#xff0c;是不同的对象去完成同一个动作所产生的结果可能有多种。这种多种的形态我们称之为多态。 比如&#xff1a;我们在买票的时候的时候&#xff0c;可能有成人全价&#xff0c;儿童半价&#xff0c;军人免票等等。对于成人&#xff0c;儿…

北斗高精度组合导航终端

UWB&#xff08;Ultra-Wideband&#xff09;、卫星定位&#xff08;GNSS&#xff09;&#xff0c;以及IMU&#xff08;Inertial Measurement Unit&#xff09;的组合定位系统结合了多种传感器和定位技术&#xff0c;以提供高精度、高可靠性的位置估计。这种组合定位系统在各种应…

五种定时任务方案(Timer+ScheduleExecutorService+spring task+多线程执行+quartz)

方案一&#xff1a;Timer (1)Timer.schedule(TimerTask task,Date time)安排在制定的时间执行指定的任务。 (2)Timer.schedule(TimerTask task,Date firstTime ,long period)安排指定的任务在指定的时间开始进行重复的固定延迟执行&#xff0e; (3)Timer.schedule(TimerTask…

网络技术十五:DHCP

DHCP 引入原因&#xff08;产生背景&#xff09; 手动为局域网中大量主机配置IP地址、掩码、网关等参数的工作繁琐&#xff0c;容易出错 DHCP可以自动为局域网中主机完成TCP/IP协议配置 DHCP自动配置避免了IP地址冲突的问题 定义 动态主机配置协议 用于为局域网中主机动态分…

文件怎么加密?文件加密软件哪个好用?

在电脑中使用重要文件时&#xff0c;我们需要保护文件的安全&#xff0c;避免数据泄露&#xff0c;而保护文件最好的方法就是文件加密。那么&#xff0c;文件该怎么加密呢&#xff1f; 超级加密3000 文件加密的首要任务就是保护数据内容的安全性&#xff0c;我们需要选择拥有超…

有哪些跨平台的办公软件,可以集成到自己的 APP中?

随着移动办公的普及&#xff0c;越来越多的跨平台办公软件被开发出来以满足不断增长的移动办公需求。这些软件不仅可以在各种操作系统中运行&#xff0c;还可以集成到自己的APP中&#xff0c;进一步提升用户的工作效率。本文将介绍一些常用的跨平台办公软件&#xff0c;并探讨如…