- 新增优惠券卡片对齐修复文档 - 新增优惠券状态显示调试文档 - 新增优惠券组件警告修复文档- 更新用ShopInfo Hook字段迁移文档 - 更新Arguments关键字修复文档
358 lines
7.8 KiB
Markdown
358 lines
7.8 KiB
Markdown
# 🏪 useShopInfo Hook 使用指南
|
||
|
||
## 📋 概述
|
||
|
||
`useShopInfo` 是一个用于管理商店信息的React Hook,提供了商店信息的获取、缓存和管理功能。它基于`getShopInfo()`接口,为全站提供统一的商店信息访问方式。
|
||
|
||
## ✨ 特性
|
||
|
||
- 🚀 **自动缓存**:30分钟本地缓存,减少网络请求
|
||
- 🔄 **智能刷新**:支持强制刷新和自动过期更新
|
||
- 📱 **离线支持**:网络失败时使用缓存数据
|
||
- 🛠️ **工具方法**:提供常用信息的便捷获取方法
|
||
- 🎯 **TypeScript**:完整的类型支持
|
||
- ⚡ **性能优化**:使用useCallback避免不必要的重渲染
|
||
|
||
## 🔧 基本用法
|
||
|
||
### 1. 导入Hook
|
||
```typescript
|
||
import { useShopInfo } from '@/hooks/useShopInfo';
|
||
```
|
||
|
||
### 2. 在组件中使用
|
||
```typescript
|
||
const MyComponent = () => {
|
||
const {
|
||
shopInfo,
|
||
loading,
|
||
error,
|
||
getWebsiteName,
|
||
getWebsiteLogo
|
||
} = useShopInfo();
|
||
|
||
if (loading) {
|
||
return <div>加载中...</div>;
|
||
}
|
||
|
||
if (error) {
|
||
return <div>加载失败: {error}</div>;
|
||
}
|
||
|
||
return (
|
||
<div>
|
||
<img src={getWebsiteLogo()} alt="Logo" />
|
||
<h1>{getWebsiteName()}</h1>
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
## 📊 API 参考
|
||
|
||
### 状态属性
|
||
|
||
| 属性 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `shopInfo` | `CmsWebsite \| null` | 商店信息对象 |
|
||
| `loading` | `boolean` | 是否正在加载 |
|
||
| `error` | `string \| null` | 错误信息 |
|
||
|
||
### 方法
|
||
|
||
| 方法 | 参数 | 返回值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `fetchShopInfo` | `forceRefresh?: boolean` | `Promise<CmsWebsite \| null>` | 获取商店信息 |
|
||
| `refreshShopInfo` | - | `Promise<CmsWebsite \| null>` | 强制刷新商店信息 |
|
||
| `clearCache` | - | `void` | 清除本地缓存 |
|
||
|
||
### 工具方法
|
||
|
||
| 方法 | 返回值 | 说明 |
|
||
|------|--------|------|
|
||
| `getWebsiteName()` | `string` | 获取网站名称,默认"商城" |
|
||
| `getWebsiteLogo()` | `string` | 获取网站Logo URL |
|
||
| `getDarkLogo()` | `string` | 获取深色模式Logo URL |
|
||
| `getDomain()` | `string` | 获取网站域名 |
|
||
| `getPhone()` | `string` | 获取联系电话 |
|
||
| `getEmail()` | `string` | 获取邮箱地址 |
|
||
| `getAddress()` | `string` | 获取地址 |
|
||
| `getIcpNo()` | `string` | 获取ICP备案号 |
|
||
| `getStatus()` | `object` | 获取网站状态信息 |
|
||
| `getConfig()` | `any` | 获取网站配置 |
|
||
| `getNavigation()` | `object` | 获取导航菜单 |
|
||
| `isSearchEnabled()` | `boolean` | 是否支持搜索 |
|
||
| `getVersionInfo()` | `object` | 获取版本信息 |
|
||
|
||
## 🎯 使用场景
|
||
|
||
### 1. 页面头部组件
|
||
```typescript
|
||
// src/pages/index/Header.tsx
|
||
import { useShopInfo } from '@/hooks/useShopInfo';
|
||
|
||
const Header = () => {
|
||
const { getWebsiteName, getWebsiteLogo, loading } = useShopInfo();
|
||
|
||
return (
|
||
<NavBar
|
||
left={
|
||
<div style={{display: 'flex', alignItems: 'center'}}>
|
||
<Avatar size="22" src={getWebsiteLogo()} />
|
||
<span>{getWebsiteName()}</span>
|
||
</div>
|
||
}
|
||
/>
|
||
);
|
||
};
|
||
```
|
||
|
||
### 2. 首页组件
|
||
```typescript
|
||
// src/pages/index/index.tsx
|
||
import { useShopInfo } from '@/hooks/useShopInfo';
|
||
|
||
const Home = () => {
|
||
const { shopInfo, loading, error } = useShopInfo();
|
||
|
||
useEffect(() => {
|
||
if (shopInfo) {
|
||
// 设置页面标题
|
||
Taro.setNavigationBarTitle({
|
||
title: shopInfo.websiteName || '商城'
|
||
});
|
||
}
|
||
}, [shopInfo]);
|
||
|
||
// 分享配置
|
||
useShareAppMessage(() => ({
|
||
title: shopInfo?.websiteName || '精选商城',
|
||
imageUrl: shopInfo?.websiteLogo
|
||
}));
|
||
|
||
return (
|
||
<div>
|
||
{/* 页面内容 */}
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
### 3. 商品详情页分享
|
||
```typescript
|
||
// src/shop/goodsDetail/index.tsx
|
||
import { useShopInfo } from '@/hooks/useShopInfo';
|
||
|
||
const GoodsDetail = () => {
|
||
const { getWebsiteName, getWebsiteLogo } = useShopInfo();
|
||
|
||
useShareAppMessage(() => ({
|
||
title: `${goods?.name} - ${getWebsiteName()}`,
|
||
path: `/shop/goodsDetail/index?id=${goodsId}`,
|
||
imageUrl: goods?.image || getWebsiteLogo()
|
||
}));
|
||
|
||
return (
|
||
<div>
|
||
{/* 商品详情 */}
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
### 4. 联系我们页面
|
||
```typescript
|
||
const ContactPage = () => {
|
||
const {
|
||
getPhone,
|
||
getEmail,
|
||
getAddress,
|
||
getIcpNo
|
||
} = useShopInfo();
|
||
|
||
return (
|
||
<div>
|
||
<div>电话: {getPhone()}</div>
|
||
<div>邮箱: {getEmail()}</div>
|
||
<div>地址: {getAddress()}</div>
|
||
<div>备案号: {getIcpNo()}</div>
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
### 5. 网站状态检查
|
||
```typescript
|
||
const StatusChecker = () => {
|
||
const { getStatus, getVersionInfo } = useShopInfo();
|
||
|
||
const status = getStatus();
|
||
const version = getVersionInfo();
|
||
|
||
return (
|
||
<div>
|
||
<div>运行状态: {status.running ? '正常' : '维护中'}</div>
|
||
<div>版本: {version.version === 10 ? '免费版' : version.version === 20 ? '专业版' : '永久授权'}</div>
|
||
{version.expirationTime && (
|
||
<div>到期时间: {version.expirationTime}</div>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
## 🔄 缓存机制
|
||
|
||
### 缓存策略
|
||
- **缓存时间**:30分钟
|
||
- **存储位置**:微信小程序本地存储
|
||
- **缓存键名**:`shop_info` 和 `shop_info_cache_time`
|
||
|
||
### 缓存行为
|
||
1. **首次加载**:从服务器获取数据并缓存
|
||
2. **后续加载**:优先使用缓存,缓存过期时自动刷新
|
||
3. **网络失败**:使用缓存数据(即使过期)
|
||
4. **强制刷新**:忽略缓存,直接从服务器获取
|
||
|
||
### 手动管理缓存
|
||
```typescript
|
||
const { refreshShopInfo, clearCache } = useShopInfo();
|
||
|
||
// 强制刷新
|
||
const handleRefresh = async () => {
|
||
await refreshShopInfo();
|
||
};
|
||
|
||
// 清除缓存
|
||
const handleClearCache = () => {
|
||
clearCache();
|
||
};
|
||
```
|
||
|
||
## 🚀 性能优化
|
||
|
||
### 1. 避免重复请求
|
||
```typescript
|
||
// ✅ 推荐:多个组件使用同一个Hook实例
|
||
const App = () => {
|
||
const shopInfo = useShopInfo();
|
||
|
||
return (
|
||
<ShopInfoProvider value={shopInfo}>
|
||
<Header />
|
||
<Content />
|
||
<Footer />
|
||
</ShopInfoProvider>
|
||
);
|
||
};
|
||
```
|
||
|
||
### 2. 条件渲染优化
|
||
```typescript
|
||
const Component = () => {
|
||
const { shopInfo, loading } = useShopInfo();
|
||
|
||
// ✅ 使用loading状态避免闪烁
|
||
if (loading) {
|
||
return <Skeleton />;
|
||
}
|
||
|
||
return (
|
||
<div>
|
||
{shopInfo && (
|
||
<img src={shopInfo.websiteLogo} alt="Logo" />
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
## 🛠️ 迁移指南
|
||
|
||
### 从直接调用API迁移
|
||
|
||
#### 迁移前 ❌
|
||
```typescript
|
||
// 旧代码
|
||
const [config, setConfig] = useState<CmsWebsite>();
|
||
|
||
useEffect(() => {
|
||
getShopInfo().then((data) => {
|
||
setConfig(data);
|
||
});
|
||
}, []);
|
||
```
|
||
|
||
#### 迁移后 ✅
|
||
```typescript
|
||
// 新代码
|
||
const { shopInfo: config, loading } = useShopInfo();
|
||
```
|
||
|
||
### 批量替换步骤
|
||
|
||
1. **替换导入**
|
||
```typescript
|
||
// 删除
|
||
import { getShopInfo } from '@/api/layout';
|
||
|
||
// 添加
|
||
import { useShopInfo } from '@/hooks/useShopInfo';
|
||
```
|
||
|
||
2. **替换状态管理**
|
||
```typescript
|
||
// 删除
|
||
const [config, setConfig] = useState<CmsWebsite>();
|
||
|
||
// 替换为
|
||
const { shopInfo: config, loading, error } = useShopInfo();
|
||
```
|
||
|
||
3. **删除useEffect**
|
||
```typescript
|
||
// 删除这些代码
|
||
useEffect(() => {
|
||
getShopInfo().then((data) => {
|
||
setConfig(data);
|
||
});
|
||
}, []);
|
||
```
|
||
|
||
## 🧪 测试示例
|
||
|
||
```typescript
|
||
// 测试组件
|
||
const TestComponent = () => {
|
||
const {
|
||
shopInfo,
|
||
loading,
|
||
error,
|
||
refreshShopInfo,
|
||
getWebsiteName
|
||
} = useShopInfo();
|
||
|
||
return (
|
||
<div>
|
||
<div>状态: {loading ? '加载中' : '已加载'}</div>
|
||
<div>错误: {error || '无'}</div>
|
||
<div>网站名: {getWebsiteName()}</div>
|
||
<button onClick={refreshShopInfo}>刷新</button>
|
||
<pre>{JSON.stringify(shopInfo, null, 2)}</pre>
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
## 🎉 总结
|
||
|
||
`useShopInfo` Hook 提供了:
|
||
|
||
- ✅ **统一的商店信息管理**
|
||
- ✅ **智能缓存机制**
|
||
- ✅ **丰富的工具方法**
|
||
- ✅ **完整的TypeScript支持**
|
||
- ✅ **简单的迁移路径**
|
||
|
||
通过使用这个Hook,你可以在整个应用中轻松访问和管理商店信息,提高代码的可维护性和用户体验。
|