227 lines
5.4 KiB
Markdown
227 lines
5.4 KiB
Markdown
# useRedDot Hook 使用指南
|
||
|
||
## 概述
|
||
|
||
`useRedDot` 是一个用于管理应用中红点提示的 React Hook。它提供了完整的红点状态管理功能,**默认显示红点,查看后消失**。
|
||
|
||
## 特性
|
||
|
||
- ✅ **默认显示逻辑**:localStorage 不存在记录时显示红点
|
||
- ✅ **自动持久化**:使用 localStorage 存储已查看状态
|
||
- ✅ **一次性显示**:查看后自动消失
|
||
- ✅ **命名空间隔离**:通过前缀避免键名冲突
|
||
- ✅ **批量操作**:支持批量标记已读和清除
|
||
- ✅ **TypeScript 支持**:完整的类型定义
|
||
|
||
## 基本用法
|
||
|
||
### 1. 导入 Hook
|
||
|
||
```typescript
|
||
import { useRedDot, RED_DOT_KEYS } from '@/hooks/useRedDot';
|
||
```
|
||
|
||
### 2. 在组件中使用
|
||
|
||
```typescript
|
||
const MyComponent = () => {
|
||
const { hasRedDot, markAsViewed, showRedDot } = useRedDot({
|
||
prefix: 'my_feature_' // 可选,默认为 'red_dot_'
|
||
});
|
||
|
||
return (
|
||
<div>
|
||
<div className="flex items-center gap-2">
|
||
<span>设置</span>
|
||
{hasRedDot('settings') && <Badge variant="dot" />}
|
||
</div>
|
||
<button onClick={() => markAsViewed('settings')}>
|
||
查看设置
|
||
</button>
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
## API 参考
|
||
|
||
### 参数
|
||
|
||
```typescript
|
||
interface UseRedDotOptions {
|
||
prefix?: string; // localStorage 键名前缀,默认 'red_dot_'
|
||
}
|
||
```
|
||
|
||
### 返回值
|
||
|
||
```typescript
|
||
interface UseRedDotReturn {
|
||
// 检查是否显示红点
|
||
hasRedDot: (key: string) => boolean;
|
||
|
||
// 标记为已查看(消除红点)
|
||
markAsViewed: (key: string) => void;
|
||
|
||
// 显示红点
|
||
showRedDot: (key: string) => void;
|
||
|
||
// 批量标记已查看
|
||
markMultipleAsViewed: (keys: string[]) => void;
|
||
|
||
// 清除所有红点
|
||
clearAllRedDots: () => void;
|
||
|
||
// 获取所有有红点的功能键
|
||
getAllRedDotKeys: () => string[];
|
||
}
|
||
```
|
||
|
||
## 预定义常量
|
||
|
||
为了避免硬编码字符串,提供了预定义的红点键:
|
||
|
||
```typescript
|
||
export const RED_DOT_KEYS = {
|
||
CHAT_BUBBLE: 'chat_bubble',
|
||
CHAT_BACKGROUND: 'chat_background',
|
||
CHAT_MODEL: 'chat_model',
|
||
PROFILE_SETTING: 'profile_setting',
|
||
} as const;
|
||
```
|
||
|
||
## 完整示例
|
||
|
||
### 聊天设置页面
|
||
|
||
```typescript
|
||
import { useRedDot, RED_DOT_KEYS } from '@/hooks/useRedDot';
|
||
import { Badge } from '@/components/ui/badge';
|
||
|
||
const ChatSettingsPage = () => {
|
||
const { hasRedDot, markAsViewed } = useRedDot({
|
||
prefix: `chat_${chatId}_`
|
||
});
|
||
|
||
const handleBubbleSettingClick = () => {
|
||
// 点击时标记为已查看
|
||
markAsViewed(RED_DOT_KEYS.CHAT_BUBBLE);
|
||
// 打开设置页面
|
||
openBubbleSettings();
|
||
};
|
||
|
||
return (
|
||
<div>
|
||
<div className="setting-item" onClick={handleBubbleSettingClick}>
|
||
<div className="flex items-center gap-2">
|
||
<span>聊天气泡</span>
|
||
{hasRedDot(RED_DOT_KEYS.CHAT_BUBBLE) && <Badge variant="dot" />}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="setting-item" onClick={() => {
|
||
markAsViewed(RED_DOT_KEYS.CHAT_BACKGROUND);
|
||
openBackgroundSettings();
|
||
}}>
|
||
<div className="flex items-center gap-2">
|
||
<span>聊天背景</span>
|
||
{hasRedDot(RED_DOT_KEYS.CHAT_BACKGROUND) && <Badge variant="dot" />}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
### 管理页面(显示红点)
|
||
|
||
```typescript
|
||
const AdminPage = () => {
|
||
const { showRedDot } = useRedDot();
|
||
|
||
const handleNewFeatureRelease = () => {
|
||
// 发布新功能时显示红点
|
||
showRedDot(RED_DOT_KEYS.CHAT_BUBBLE);
|
||
showRedDot(RED_DOT_KEYS.CHAT_BACKGROUND);
|
||
};
|
||
|
||
return (
|
||
<button onClick={handleNewFeatureRelease}>
|
||
发布聊天新功能
|
||
</button>
|
||
);
|
||
};
|
||
```
|
||
|
||
## 高级用法
|
||
|
||
### 1. 不同用户/场景的隔离
|
||
|
||
```typescript
|
||
// 为不同用户使用不同前缀
|
||
const userARedDot = useRedDot({ prefix: `user_${userA.id}_` });
|
||
const userBRedDot = useRedDot({ prefix: `user_${userB.id}_` });
|
||
|
||
// 为不同功能模块使用不同前缀
|
||
const chatRedDot = useRedDot({ prefix: 'chat_' });
|
||
const profileRedDot = useRedDot({ prefix: 'profile_' });
|
||
```
|
||
|
||
### 2. 批量操作
|
||
|
||
```typescript
|
||
const { markMultipleAsViewed, clearAllRedDots } = useRedDot();
|
||
|
||
// 用户查看了整个设置页面,标记多个功能为已读
|
||
const handleSettingsPageVisit = () => {
|
||
markMultipleAsViewed([
|
||
RED_DOT_KEYS.CHAT_BUBBLE,
|
||
RED_DOT_KEYS.CHAT_BACKGROUND,
|
||
RED_DOT_KEYS.CHAT_MODEL
|
||
]);
|
||
};
|
||
|
||
// 重置所有红点(比如用户重新登录)
|
||
const handleUserLogin = () => {
|
||
clearAllRedDots();
|
||
};
|
||
```
|
||
|
||
### 3. 状态监控
|
||
|
||
```typescript
|
||
const { getAllRedDotKeys, hasRedDot } = useRedDot();
|
||
|
||
// 获取当前所有未读功能
|
||
const unreadFeatures = getAllRedDotKeys();
|
||
console.log('用户有', unreadFeatures.length, '个未读功能');
|
||
|
||
// 检查是否有任何未读
|
||
const hasAnyUnread = unreadFeatures.length > 0;
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **localStorage 限制**:确保浏览器支持 localStorage
|
||
2. **前缀命名**:使用有意义的前缀避免冲突
|
||
3. **性能考虑**:避免在 render 方法中频繁调用 showRedDot
|
||
4. **错误处理**:Hook 内部已处理 localStorage 异常
|
||
|
||
## 存储格式
|
||
|
||
红点状态在 localStorage 中的存储格式:
|
||
|
||
```
|
||
键名: ${prefix}${redDotKey}
|
||
值: 'viewed' | undefined (删除)
|
||
```
|
||
|
||
**重要逻辑**:
|
||
- **不存在记录** = 显示红点(默认状态)
|
||
- **存在 'viewed' 记录** = 不显示红点(已查看)
|
||
|
||
例如:
|
||
- 无记录 -> 显示红点
|
||
- `chat_123_chat_bubble: 'viewed'` -> 不显示红点
|
||
- `profile_settings: 'viewed'` -> 不显示红点
|