基于 Vue 简单实现一个 message 提示框
大约 2 分钟
在日常开发中,像 Message.success()、Message.error() 这类 API 式调用的提示框非常常见,例如 Element Plus、Ant Design Vue 都提供了类似能力。
本文基于 Vue 3,从最简单的实现入手,手写一个 message 提示框,帮助理解这类组件背后的实现原理。
一、Message 的实现思路
API 式 message 的核心思想可以总结为一句话:
在需要的时候,动态创建一个组件实例,并挂载到
body上
具体步骤如下:
- 使用
createApp创建一个 Vue 应用实例 - 将 message 组件挂载到一个动态创建的 DOM 节点
- 插入到
document.body - 在指定时间后销毁组件并移除 DOM
二、创建 Message 组件
首先实现一个最基础的 Message 组件,仅负责展示内容。
<template>
<div class="message">
{{ message }}
</div>
</template>
<script setup>
defineProps({
message: String,
})
</script>
<style>
.message {
position: fixed;
top: 20px;
right: 20px;
background: black;
color: white;
padding: 12px 16px;
border-radius: 4px;
z-index: 9999;
}
</style>
这里有几个关键点:
- 使用
position: fixed,避免受父级布局影响 - 提示框不参与页面布局
- 样式尽量保持简单,聚焦功能本身
三、通过 createApp 动态创建组件
接下来实现核心的 message 函数。
import { createApp } from 'vue'
import MyMessage from './MyMessage.vue'
function createMessage(options) {
const { text = '', duration = 2000 } = options || {}
// 1. 创建一个容器
const container = document.createElement('div')
// 2. 创建应用实例
const app = createApp(MyMessage, {
message: text,
})
// 3. 挂载并插入 body
app.mount(container)
document.body.appendChild(container)
// 4. 定时销毁
setTimeout(() => {
app.unmount()
document.body.removeChild(container)
}, duration)
}
export function message(text) {
createMessage({ text })
}
调用方式如下:
message('操作成功')
四、为什么要手动 unmount?
这里有一个很容易被忽略但非常重要的点:
app.unmount()
document.body.removeChild(container)
如果只移除 DOM,不卸载 Vue 实例:
- 组件的响应式依然存在
- 定时器、watch、事件监听可能不会释放
- 多次调用会造成 内存泄漏
Loading...
