feat: new project
This commit is contained in:
387
docs/LIBRARIES.md
Normal file
387
docs/LIBRARIES.md
Normal file
@@ -0,0 +1,387 @@
|
||||
# 📚 常用工具库使用指南
|
||||
|
||||
本文档介绍项目中已安装的常用工具库及其使用方法。
|
||||
|
||||
## 📦 已安装的库列表
|
||||
|
||||
### 工具类库
|
||||
| 库名 | 版本 | 用途 |
|
||||
|------|------|------|
|
||||
| **lodash-es** | ^4.17.21 | JavaScript 工具函数库(ES modules 版本) |
|
||||
| **dayjs** | ^1.11.19 | 轻量级日期处理库 |
|
||||
| **axios** | ^1.13.1 | HTTP 请求库 |
|
||||
| **zustand** | ^5.0.8 | 轻量级状态管理 |
|
||||
| **react-hook-form** | ^7.66.0 | 表单处理库 |
|
||||
| **zod** | ^4.1.12 | TypeScript 数据验证库 |
|
||||
|
||||
### Expo 原生模块
|
||||
| 库名 | 版本 | 用途 |
|
||||
|------|------|------|
|
||||
| **@react-native-async-storage/async-storage** | ^2.2.0 | 本地存储 |
|
||||
| **expo-image** | ^3.0.10 | 优化的图片组件 |
|
||||
| **expo-haptics** | ^15.0.7 | 触觉反馈 |
|
||||
|
||||
### 开发工具
|
||||
| 库名 | 版本 | 用途 |
|
||||
|------|------|------|
|
||||
| **@types/lodash-es** | ^4.17.12 | Lodash-ES TypeScript 类型定义 |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 1. Lodash-ES - JavaScript 工具库
|
||||
|
||||
> **注意**:使用 `lodash-es` 而不是 `lodash`,支持 ES modules 和更好的 tree-shaking。
|
||||
|
||||
```typescript
|
||||
// 推荐:按需导入(tree-shaking 友好)
|
||||
import { map, filter, uniq, pick, cloneDeep, debounce } from 'lodash-es';
|
||||
|
||||
// 数组操作
|
||||
map([1, 2, 3], n => n * 2); // [2, 4, 6]
|
||||
filter([1, 2, 3, 4], n => n % 2 === 0); // [2, 4]
|
||||
uniq([1, 2, 2, 3]); // [1, 2, 3]
|
||||
|
||||
// 对象操作
|
||||
pick({ a: 1, b: 2, c: 3 }, ['a', 'b']); // { a: 1, b: 2 }
|
||||
cloneDeep(obj); // 深拷贝
|
||||
|
||||
// 防抖和节流
|
||||
const handleSearch = debounce((text) => {
|
||||
console.log('Searching:', text);
|
||||
}, 300);
|
||||
|
||||
// 也可以全量导入(不推荐,会增加包体积)
|
||||
import _ from 'lodash-es';
|
||||
_.map([1, 2, 3], n => n * 2);
|
||||
```
|
||||
|
||||
### 2. Day.js - 日期处理
|
||||
|
||||
```typescript
|
||||
import dayjs from 'dayjs';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import 'dayjs/locale/zh-cn';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
dayjs.locale('zh-cn');
|
||||
|
||||
// 格式化
|
||||
dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||||
|
||||
// 相对时间
|
||||
dayjs().fromNow(); // '几秒前'
|
||||
dayjs().subtract(1, 'day').fromNow(); // '1天前'
|
||||
|
||||
// 日期操作
|
||||
dayjs().add(7, 'day'); // 7天后
|
||||
dayjs().startOf('month'); // 本月第一天
|
||||
```
|
||||
|
||||
### 3. Axios - HTTP 请求
|
||||
|
||||
```typescript
|
||||
import axios from 'axios';
|
||||
|
||||
// 创建实例
|
||||
const api = axios.create({
|
||||
baseURL: 'https://api.example.com',
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
// 请求拦截器
|
||||
api.interceptors.request.use(async (config) => {
|
||||
const token = await AsyncStorage.getItem('token');
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
||||
// 使用
|
||||
const data = await api.get('/users');
|
||||
await api.post('/users', { name: 'John' });
|
||||
```
|
||||
|
||||
### 4. Zustand - 状态管理
|
||||
|
||||
```typescript
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface UserState {
|
||||
user: User | null;
|
||||
setUser: (user: User) => void;
|
||||
}
|
||||
|
||||
export const useUserStore = create<UserState>((set) => ({
|
||||
user: null,
|
||||
setUser: (user) => set({ user }),
|
||||
}));
|
||||
|
||||
// 在组件中使用
|
||||
const user = useUserStore((state) => state.user);
|
||||
const setUser = useUserStore((state) => state.setUser);
|
||||
```
|
||||
|
||||
### 5. React Hook Form + Zod - 表单处理
|
||||
|
||||
```typescript
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { z } from 'zod';
|
||||
|
||||
const schema = z.object({
|
||||
email: z.string().email('请输入有效的邮箱'),
|
||||
password: z.string().min(6, '密码至少6个字符'),
|
||||
});
|
||||
|
||||
type FormData = z.infer<typeof schema>;
|
||||
|
||||
function LoginForm() {
|
||||
const { control, handleSubmit, formState: { errors } } = useForm<FormData>({
|
||||
resolver: zodResolver(schema),
|
||||
});
|
||||
|
||||
const onSubmit = (data: FormData) => {
|
||||
console.log(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<Controller
|
||||
control={control}
|
||||
name="email"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<TextInput
|
||||
value={value}
|
||||
onChangeText={onChange}
|
||||
placeholder="邮箱"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 6. AsyncStorage - 本地存储
|
||||
|
||||
```typescript
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
// 存储
|
||||
await AsyncStorage.setItem('key', JSON.stringify(value));
|
||||
|
||||
// 读取
|
||||
const value = await AsyncStorage.getItem('key');
|
||||
const data = value ? JSON.parse(value) : null;
|
||||
|
||||
// 删除
|
||||
await AsyncStorage.removeItem('key');
|
||||
|
||||
// 清空
|
||||
await AsyncStorage.clear();
|
||||
```
|
||||
|
||||
### 7. Expo Image - 优化的图片组件
|
||||
|
||||
```typescript
|
||||
import { Image } from 'expo-image';
|
||||
|
||||
<Image
|
||||
source={{ uri: 'https://example.com/image.jpg' }}
|
||||
placeholder={require('@/assets/placeholder.png')}
|
||||
contentFit="cover"
|
||||
transition={1000}
|
||||
style={{ width: 300, height: 300 }}
|
||||
/>
|
||||
```
|
||||
|
||||
### 8. Expo Haptics - 触觉反馈
|
||||
|
||||
```typescript
|
||||
import * as Haptics from 'expo-haptics';
|
||||
|
||||
// 轻触反馈
|
||||
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
|
||||
|
||||
// 成功反馈
|
||||
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
|
||||
|
||||
// 错误反馈
|
||||
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 实用示例
|
||||
|
||||
### 创建 API 工具类
|
||||
|
||||
```typescript
|
||||
// utils/api.ts
|
||||
import axios from 'axios';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: 'https://api.example.com',
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
api.interceptors.request.use(async (config) => {
|
||||
const token = await AsyncStorage.getItem('token');
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
||||
api.interceptors.response.use(
|
||||
(response) => response.data,
|
||||
(error) => {
|
||||
if (error.response?.status === 401) {
|
||||
AsyncStorage.removeItem('token');
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
export default api;
|
||||
```
|
||||
|
||||
### 创建 Storage 工具类
|
||||
|
||||
```typescript
|
||||
// utils/storage.ts
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
class Storage {
|
||||
static async setObject<T>(key: string, value: T): Promise<void> {
|
||||
await AsyncStorage.setItem(key, JSON.stringify(value));
|
||||
}
|
||||
|
||||
static async getObject<T>(key: string): Promise<T | null> {
|
||||
const value = await AsyncStorage.getItem(key);
|
||||
return value ? JSON.parse(value) : null;
|
||||
}
|
||||
|
||||
static async remove(key: string): Promise<void> {
|
||||
await AsyncStorage.removeItem(key);
|
||||
}
|
||||
}
|
||||
|
||||
export default Storage;
|
||||
```
|
||||
|
||||
### 创建用户状态管理
|
||||
|
||||
```typescript
|
||||
// stores/userStore.ts
|
||||
import { create } from 'zustand';
|
||||
import { persist, createJSONStorage } from 'zustand/middleware';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
interface UserState {
|
||||
user: User | null;
|
||||
setUser: (user: User) => void;
|
||||
clearUser: () => void;
|
||||
}
|
||||
|
||||
export const useUserStore = create<UserState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
user: null,
|
||||
setUser: (user) => set({ user }),
|
||||
clearUser: () => set({ user: null }),
|
||||
}),
|
||||
{
|
||||
name: 'user-storage',
|
||||
storage: createJSONStorage(() => AsyncStorage),
|
||||
}
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
### 日期格式化工具
|
||||
|
||||
```typescript
|
||||
// utils/date.ts
|
||||
import dayjs from 'dayjs';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import 'dayjs/locale/zh-cn';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
dayjs.locale('zh-cn');
|
||||
|
||||
export const formatDate = (date: Date | string | number) => {
|
||||
return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
|
||||
};
|
||||
|
||||
export const formatRelativeTime = (date: Date | string | number) => {
|
||||
return dayjs(date).fromNow();
|
||||
};
|
||||
|
||||
export const formatChatTime = (timestamp: number) => {
|
||||
const date = dayjs(timestamp);
|
||||
const now = dayjs();
|
||||
|
||||
if (date.isSame(now, 'day')) {
|
||||
return date.format('HH:mm');
|
||||
} else if (date.isSame(now.subtract(1, 'day'), 'day')) {
|
||||
return '昨天 ' + date.format('HH:mm');
|
||||
} else if (date.isSame(now, 'year')) {
|
||||
return date.format('MM-DD HH:mm');
|
||||
} else {
|
||||
return date.format('YYYY-MM-DD');
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 最佳实践
|
||||
|
||||
1. **代码组织**
|
||||
- 将 API 配置放在 `utils/api.ts`
|
||||
- 将存储工具放在 `utils/storage.ts`
|
||||
- 将状态管理放在 `stores/` 目录
|
||||
- 将验证规则放在 `schemas/` 目录
|
||||
|
||||
2. **性能优化**
|
||||
- 使用 `_.debounce` 和 `_.throttle` 优化频繁触发的事件
|
||||
- 使用 Zustand 的选择器避免不必要的重渲染
|
||||
- 使用 Expo Image 的缓存策略
|
||||
|
||||
3. **类型安全**
|
||||
- 使用 Zod 定义数据结构并自动生成 TypeScript 类型
|
||||
- 为 Zustand store 定义完整的类型
|
||||
- 使用 `@types/lodash` 获得完整的类型提示
|
||||
|
||||
4. **错误处理**
|
||||
- 在 Axios 拦截器中统一处理错误
|
||||
- 使用 try-catch 包裹异步操作
|
||||
- 提供用户友好的错误提示
|
||||
|
||||
---
|
||||
|
||||
## 🔗 相关资源
|
||||
|
||||
- [Lodash 文档](https://lodash.com/docs/)
|
||||
- [Day.js 文档](https://day.js.org/)
|
||||
- [Axios 文档](https://axios-http.com/)
|
||||
- [Zustand 文档](https://zustand-demo.pmnd.rs/)
|
||||
- [React Hook Form 文档](https://react-hook-form.com/)
|
||||
- [Zod 文档](https://zod.dev/)
|
||||
- [AsyncStorage 文档](https://react-native-async-storage.github.io/async-storage/)
|
||||
- [Expo Image 文档](https://docs.expo.dev/versions/latest/sdk/image/)
|
||||
- [Expo Haptics 文档](https://docs.expo.dev/versions/latest/sdk/haptics/)
|
||||
|
||||
---
|
||||
|
||||
**提示**:所有库都已安装并配置好,可以直接在项目中使用!🎉
|
||||
|
||||
Reference in New Issue
Block a user