在React中, Toast 是一种轻量级的通知组件,主要用于向用户展示简短的操作反馈或状态提示。它通常具有以下特点和作用:
核心含义
Toast 源自移动端开发(如Android/iOS),在React中被广泛借鉴,本质是 临时消息提示框 ,会在屏幕上短暂显示后自动消失,不会阻塞用户操作。
主要作用
-
操作结果反馈
- 成功提示(如"提交成功")、错误提示(如"网络异常")
- 加载状态(如"数据加载中...")
-
轻量级通知
- 相比模态框(Modal)更简洁,不需要用户手动关闭
- 适合展示非关键性信息(如"已保存草稿")
-
用户体验优化
- 提供即时视觉反馈,增强交互感知
- 避免打断用户当前操作流程
那么什么是 mitt?
mitt
是一个超轻量级的 JavaScript 事件发射器库(gzip 压缩后仅 200 bytes),它实现了 发布-订阅模式 (Pub/Sub),允许你在应用的不同组件之间建立松耦合的通信机制。
简单说,mitt
就像一个"事件邮局":
- 组件可以"订阅"感兴趣的事件(留下联系方式)
- 其他组件可以"发布"事件(寄信)
- 邮局负责将事件传递给所有订阅者
核心 API(极简设计)
import mitt from 'mitt'
const emitter = mitt()
// 订阅事件
emitter.on('eventName', (data) => { /* 处理事件 */ })
// 发布事件
emitter.emit('eventName', { message: 'Hello' })
// 取消订阅
emitter.off('eventName', handler)
// 清除所有事件
emitter.all.clear()
具体作用
在项目逻辑中,mitt
被用作 全局事件总线 ,专门处理 Toast
组件的显示/隐藏逻辑:
1. 实现跨组件通信
Toast
组件通常需要在应用的任何地方被触发(如表单提交成功、网络错误等)。通过 mitt
可以避免组件间的层层传递:
首先在 toastController.js
中创建事件总线
import mitt from 'mitt';
const emitter = mitt(); // 实例化
export default emitter;
然后在 Toast
组件中订阅事件
import emitter from './toastController';
useEffect(() => {
// 监听 toast 显示事件
emitter.on('showToast', (options) => {
setVisible(true);
setMessage(options.message);
// ... 其他逻辑
});
// 组件卸载时取消订阅
return () => emitter.off('showToast');
}, []);
最后在任何组件中发布事件(触发 Toast)
import emitter from './toastController';
submitForm = () => {
api.submit().then(() => {
emitter.emit('showToast', {
message: '提交成功',
type: 'success'
});
});
};
2. 解耦 Toast 逻辑
没有 mitt
时,你可能需要:
- 通过 props 层层传递
Toast
控制函数 - 使用 Context 或 Redux 管理
Toast
状态 - 直接操作 DOM(非常不 React)
而有了 mitt
后,Toast
组件的逻辑被完全封装,其他组件只需关注事件发布,无需关心 Toast
如何实现。
3. 支持多类型事件扩展
除了显示 Toast,还可以轻松扩展其他事件类型:
// 错误提示
emitter.emit('showError', { message: '网络异常' });
// 加载提示
emitter.emit('showLoading', { text: '加载中...' });
项目中的应用:
比如说现在有这样一个页面:
我们需要在首页(或者其他地方)放置一个按钮,能够帮我们展示 我的 里面的信息,就需要用到 mitt 来处理 Toast 组件的显示逻辑:
// 让组件基于事件机制来通信
import mitt from 'mitt'; // 自定义事件
// 实例化
export const toastEvents =mitt();
export function showToast(user = 0, bell = 0, mail = 0) {
// 任何想要与Toast 通信的地方调用
// emit 发布事件 发布者
toastEvents.emit('show',{user,bell,mail});
}
Toast组件:
import { useState,useEffect } from 'react'
import { toastEvents } from './toastController';
const Toast = (props)=>{
const [visible,setIsVisible] = useState(false);
const [data,setData] = useState({
user: 0,
bell: 0,
mail: 0
});
useEffect(()=>{
const show = (info)=>{
setData(info);
setIsVisible(true);
setTimeout(()=>{
setIsVisible(false);
},2000);
}
// toastEvents 是 mitt 的实例
// 自定义事件
// on 监听一个事件
// 订阅了show 的事件,订阅者
toastEvents.on('show',show);
// 组件销毁时,取消订阅
return ()=>{
toastEvents.off('show',show);
}
},[])
if(!visible) return null;
return (
<div className={styles.toastWrapper}>
<div className={styles.toastItem}>👤 {data.user}</div>
<div className={styles.toastItem}>🔔 {data.bell}</div>
<div className={styles.toastItem}>✉️ {data.mail}</div>
<div className={styles.toastArrow}></div>
</div>
)
}
export default Toast;
然后在首页进行调用:
const Home = () => {
useTitle('Go Where Well');
return (
<div className={styles.container}>
<Button type="primary" onClick={()=>{
{* 调用 Toast *}
showToast(1,2,3);
}}>
显示Toast
</Button>
</div>
)
}
最后效果如图所示:
总结
mitt
在项目中扮演了"通信桥梁"的角色,它让 Toast
组件从全局状态管理中解放出来,实现了真正的组件解耦。这种模式特别适合:
- 全局提示组件(Toast/Modal/Notification)
- 跨组件状态同步
- 插件化架构设计
下次当你需要在 React 项目中实现简单高效的组件通信时,不妨试试 mitt
——小而美的解决方案往往最能解决实际问题!