「我们一起做组件库🌻」虚拟消息队列?message组件有何不同?(VersakitUI开发实录)

Hi, 这里是和朋友一起开发组件库的JustHappy,今天我们来做个message组件,这和我们平时编写的一般的Vue组件可能有所不同,不能单纯的借助于template范式去构建,所以具体是怎么样的呢?我们来聊聊吧!

我们的组件会是什么样的?🧐

就像下面这样,是一个显示在最上层的消息提示组件,先进先出......

什么是消息队列?什么是虚拟消息队列?🔍

在这里我们提到一个概念:虚拟消息队列。这其实是一个很常见的设计模式,用于在前端界面中有序管理通知类UI组件的显示:

  • 虚拟:不是依赖真实的数据结构(比如链表、队列),而是通过状态和DOM元素的控制来模拟队列效果;
  • 先进先出(FIFO) :保证每条信息都是排好队的,前一条展示完才轮到下一条;
  • 并发控制:最多展示几条、展示多久、自动销毁等,都可以通过"虚拟消息队列"控制。

这样,用户体验就更加可控、整洁,也避免了多条消息同时展示导致的界面混乱。

template VS render()?

聊一聊编程范式👾

什么是编程范式?如果你有编写过C语言 那你一定听过 面向过程编程 或者说是 命令式编程,如果你学习过 JavaC++ 那你对 面向对象编程 一定不陌生。

那难道我只能使用C语言编写 面向过程编程 的程序吗?我只能使用 面向对象编程 去编写Java 或者 C++ 吗?

答案当然是否定的!

以上这些其实都是我们说的 编程范式(Programming Paradigm) ,可以简单理解为编程的方法论,是解决问题的一种思想方式。

声明式 ? 函数式?

Vue 是一个以"声明式"编程为主导的前端框架,而template 模板是这种范式的代表:

html 复制代码
<template>
  <div class="msg">{{ text }}</div>
</template>

我们只需要"描述"希望界面显示成什么样,Vue 会帮我们处理后续的渲染、更新等。这个体验几乎上和编写HTML没什么区别,这也是Vue渐进式的一种体现

template 完美吗?🙃

当然也不是完美的,比如我觉得至少是有一下几点的:

  1. 语法限制:对于复杂的条件渲染、动态逻辑、嵌套结构来说,template 有点吃力;
  2. 灵活性不足:和 JSX 比较起来,template 更加"死板",不利于灵活构建动态组件结构;
  3. 功能隔离不明显:逻辑代码和视图容易耦合在一起,稍复杂点维护起来很头疼。

那我们还有别的选择吗?🛠

当然有,Vue 提供了另一套思路 ------ render()函数 + h()函数去编写JSX

Vue官网也提供了相对应的简单教程:渲染函数 & JSX | Vue.js

总得来说会像下面这样

js 复制代码
import { h } from 'vue'

export default {
  render() {
    return h('div', { class: 'msg' }, 'Hello Render')
  },
}

就是 "函数式组件" 的雏形,我们通过代码逻辑生成虚拟DOM结构,灵活性非常强!

配合 Composition API、动态挂载、VNode 创建等功能,我们就可以实现那些"不写在 template 中"的组件。

传统Vue组件和"函数式调用组件"??

什么是服务式组件?

服务式组件(Service-based Component)是一种 "用函数调用来使用组件"的模式,它是 Vue 组件使用的一种程序式调用方式(Programmatic usage)

它不依赖于 <template> 中的标签,也不会在 .vue 文件里声明组件引用,而是:

  • 通过 createVNode() 创建组件实例
  • render() 手动挂载到 DOM
  • 控制生命周期、传参、展示与销毁

适用于全局唯一、轻量弹出、无需响应父子通信的组件,比如:

  • Message 消息提示
  • Notification 通知弹窗
  • Modal 弹窗确认框
  • Toast 提示气泡

一个简单的示例实现Message的逻辑

我们也是需要依托template模板去构建插槽

html 复制代码
<!-- Message.vue -->
<template>
  <div class="message" :class="type">{{ message }}</div>
</template>
<script setup>
defineProps({ type: String, message: String })
</script>
<style scoped>
.message {
  padding: 10px;
  margin: 8px;
  border-radius: 4px;
  color: white;
  background-color: gray;
}
.message.success {
  background-color: green;
}
</style>

但是核心的虚拟消息队列会是像下面这样的

js 复制代码
// message.ts
import { h, render } from 'vue'
import Message from './Message.vue'

const queue: HTMLElement[] = []

export function showMessage({ type, message, duration = 2000 }) {
  const container = document.createElement('div')
  document.body.appendChild(container)
  const vnode = h(Message, { type, message })
  render(vnode, container)

  queue.push(container)

  setTimeout(() => {
    render(null, container)
    container.remove()
    queue.shift()
  }, duration)

如果您想看实际的实现,可以点击这里去到源码🚀🚀

最后......

欢迎大家 star✨ 支持,您的反馈是我们前进的动力!✨

相关推荐
veneno6 小时前
大量异步并发请求控制并发解决方案
前端
i***t9196 小时前
Spring Boot项目接收前端参数的11种方式
前端·spring boot·后端
oden6 小时前
2025博客框架选择指南:Hugo、Astro、Hexo该选哪个?
前端·html
小光学长6 小时前
基于ssm的宠物交易系统的设计与实现850mb48h(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
java·前端·数据库
云中飞鸿7 小时前
函数:委托
javascript
小小前端要继续努力7 小时前
渐进增强、优雅降级及现代Web开发技术详解
前端
老前端的功夫8 小时前
前端技术选型的理性之道:构建可量化的ROI评估模型
前端·javascript·人工智能·ubuntu·前端框架
汝生淮南吾在北8 小时前
SpringBoot+Vue超市收银管理系统
vue.js·spring boot·后端
狮子座的男孩8 小时前
js函数高级:04、详解执行上下文与执行上下文栈(变量提升与函数提升、执行上下文、执行上下文栈)及相关面试题
前端·javascript·经验分享·变量提升与函数提升·执行上下文·执行上下文栈·相关面试题
p***93038 小时前
SpringBoot + vue 管理系统
vue.js·spring boot·后端