@doubao-apps/ai 0.0.25 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/994.js +6 -6
- package/dist/contexts/doubao-apps-dev/.ai/examples/common-patterns.md +600 -0
- package/dist/contexts/doubao-apps-dev/.ai/examples/component-basics.md +509 -0
- package/dist/contexts/doubao-apps-dev/.ai/guides/best-practices.md +571 -0
- package/dist/contexts/doubao-apps-dev/.ai/guides/component-development.md +857 -0
- package/dist/contexts/doubao-apps-dev/.ai/guides/performance-optimization.md +404 -0
- package/dist/contexts/doubao-apps-dev/.ai/guides/system-prompt.md +331 -0
- package/dist/contexts/doubao-apps-dev/.ai/guides/troubleshooting.md +291 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/components-quick-ref.md +103 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/framework-api-quick-ref.md +537 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/01-/345/237/272/347/241/200-/350/264/246/345/217/267-/347/263/273/347/273/237.md +699 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/02-/345/255/230/345/202/250.md +409 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/03-/350/267/257/347/224/261.md +165 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/04-/347/225/214/351/235/242-/344/272/244/344/272/222.md +432 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/05-/347/225/214/351/235/242-/350/276/223/345/205/245.md +42 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/06-/347/275/221/347/273/234.md +148 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/07-/345/252/222/344/275/223.md +346 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/08-/345/274/200/346/224/276/350/203/275/345/212/233-/344/270/232/345/212/241/350/203/275/345/212/233.md +546 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/09-/350/256/276/345/244/207-/350/223/235/347/211/231.md +961 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/10-/350/256/276/345/244/207-wi-fi.md +277 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/11-/350/256/276/345/244/207-/345/212/240/351/200/237/345/272/246/350/256/241.md +104 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/12-/350/256/276/345/244/207-ibeacon.md +148 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/13-/350/256/276/345/244/207-/347/275/227/347/233/230.md +82 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/14-/350/256/276/345/244/207-/350/256/276/345/244/207/346/226/271/345/220/221.md +70 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/15-/350/256/276/345/244/207-/351/231/200/350/236/272/344/273/252.md +104 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/16-ui-/350/276/223/345/205/245.md +65 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/17-/350/256/276/345/244/207-/347/275/221/347/273/234.md +164 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/18-/350/256/276/345/244/207-/347/237/255/344/277/241.md +62 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/19-/350/256/276/345/244/207-/346/227/240/351/232/234/347/242/215.md +43 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/20-/350/256/276/345/244/207-/347/224/265/346/261/240.md +83 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/21-/350/256/276/345/244/207-/346/227/245/345/216/206.md +215 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/22-/350/256/276/345/244/207-/345/211/252/350/264/264/346/235/277.md +70 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/23-/350/256/276/345/244/207-/350/201/224/347/263/273/344/272/272.md +270 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/24-/350/256/276/345/244/207-/345/212/240/345/257/206.md +56 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/25-/350/256/276/345/244/207-/347/224/265/350/257/235.md +41 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/26-/350/256/276/345/244/207-/346/211/253/347/240/201.md +100 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/27-/350/256/276/345/244/207-/345/261/217/345/271/225.md +173 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/28-/350/256/276/345/244/207-/351/234/207/345/212/250.md +66 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api/README.md +36 -0
- package/dist/contexts/doubao-apps-dev/.ai/reference/open-api.md +326 -0
- package/dist/contexts/doubao-apps-dev/.ai/rules/dos-and-donts.md +390 -0
- package/dist/{skills → contexts}/doubao-apps-dev/AGENTS.md +56 -33
- package/dist/{skills → contexts}/doubao-apps-dev/CLAUDE.md +1 -1
- package/dist/manifest.json +45 -0
- package/dist/skills/doubao-apps-dev/.ai/examples/common-patterns.md +53 -43
- package/dist/skills/doubao-apps-dev/.ai/examples/component-basics.md +0 -17
- package/dist/skills/doubao-apps-dev/.ai/guides/component-development.md +96 -214
- package/dist/skills/doubao-apps-dev/.ai/guides/system-prompt.md +14 -14
- package/dist/skills/doubao-apps-dev/.ai/reference/framework-api-quick-ref.md +46 -85
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/01-/345/237/272/347/241/200-/350/264/246/345/217/267-/347/263/273/347/273/237.md +699 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/02-/345/255/230/345/202/250.md +409 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/03-/350/267/257/347/224/261.md +165 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/04-/347/225/214/351/235/242-/344/272/244/344/272/222.md +432 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/05-/347/225/214/351/235/242-/350/276/223/345/205/245.md +42 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/06-/347/275/221/347/273/234.md +148 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/07-/345/252/222/344/275/223.md +346 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/08-/345/274/200/346/224/276/350/203/275/345/212/233-/344/270/232/345/212/241/350/203/275/345/212/233.md +546 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/09-/350/256/276/345/244/207-/350/223/235/347/211/231.md +961 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/10-/350/256/276/345/244/207-wi-fi.md +277 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/11-/350/256/276/345/244/207-/345/212/240/351/200/237/345/272/246/350/256/241.md +104 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/12-/350/256/276/345/244/207-ibeacon.md +148 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/13-/350/256/276/345/244/207-/347/275/227/347/233/230.md +82 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/14-/350/256/276/345/244/207-/350/256/276/345/244/207/346/226/271/345/220/221.md +70 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/15-/350/256/276/345/244/207-/351/231/200/350/236/272/344/273/252.md +104 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/16-ui-/350/276/223/345/205/245.md +65 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/17-/350/256/276/345/244/207-/347/275/221/347/273/234.md +164 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/18-/350/256/276/345/244/207-/347/237/255/344/277/241.md +62 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/19-/350/256/276/345/244/207-/346/227/240/351/232/234/347/242/215.md +43 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/20-/350/256/276/345/244/207-/347/224/265/346/261/240.md +83 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/21-/350/256/276/345/244/207-/346/227/245/345/216/206.md +215 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/22-/350/256/276/345/244/207-/345/211/252/350/264/264/346/235/277.md +70 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/23-/350/256/276/345/244/207-/350/201/224/347/263/273/344/272/272.md +270 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/24-/350/256/276/345/244/207-/345/212/240/345/257/206.md +56 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/25-/350/256/276/345/244/207-/347/224/265/350/257/235.md +41 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/26-/350/256/276/345/244/207-/346/211/253/347/240/201.md +100 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/27-/350/256/276/345/244/207-/345/261/217/345/271/225.md +173 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/28-/350/256/276/345/244/207-/351/234/207/345/212/250.md +66 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api/README.md +36 -0
- package/dist/skills/doubao-apps-dev/.ai/reference/open-api.md +267 -4542
- package/dist/skills/doubao-apps-dev/.ai/rules/dos-and-donts.md +50 -37
- package/dist/skills/doubao-apps-dev/SKILL.md +57 -29
- package/dist/skills/douyin-to-doubao/SKILL.md +2 -2
- package/dist/skills/h5-to-doubao/SKILL.md +2 -2
- package/dist/skills/uniapp-to-doubao/SKILL.md +2 -2
- package/dist/skills/weixin-to-doubao/SKILL.md +2 -2
- package/package.json +4 -2
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
# 性能优化
|
|
2
|
+
|
|
3
|
+
Doubao Apps SDK 应用的性能优化指南和最佳实践。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ⚡ 渲染性能优化
|
|
8
|
+
|
|
9
|
+
### 1. 避免不必要的渲染
|
|
10
|
+
|
|
11
|
+
#### 使用 useMemo 缓存计算结果
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
// ✅ 好的做法 - 缓存昂贵的计算
|
|
15
|
+
function DataList({ items, filter }: Props) {
|
|
16
|
+
// 只在 items 或 filter 改变时重新计算
|
|
17
|
+
const filteredAndSorted = useMemo(() => {
|
|
18
|
+
console.log('Computing filtered list...');
|
|
19
|
+
return items
|
|
20
|
+
.filter(item => item.type === filter)
|
|
21
|
+
.sort((a, b) => b.score - a.score);
|
|
22
|
+
}, [items, filter]);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<list>
|
|
26
|
+
{filteredAndSorted.map(item => (
|
|
27
|
+
<ItemCard key={item.id} {...item} />
|
|
28
|
+
))}
|
|
29
|
+
</list>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ❌ 不好的做法 - 每次渲染都重新计算
|
|
34
|
+
function DataList({ items, filter }: Props) {
|
|
35
|
+
// 每次组件渲染都会执行
|
|
36
|
+
const filteredAndSorted = items
|
|
37
|
+
.filter(item => item.type === filter)
|
|
38
|
+
.sort((a, b) => b.score - a.score);
|
|
39
|
+
|
|
40
|
+
return <list>{/* ... */}</list>;
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### 使用 useCallback 稳定函数引用
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
// ✅ 好的做法 - 稳定的回调函数
|
|
48
|
+
function ParentComponent({ items }: Props) {
|
|
49
|
+
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
50
|
+
|
|
51
|
+
// 函数引用保持稳定,子组件不会因此重新渲染
|
|
52
|
+
const handleSelect = useCallback((id: string) => {
|
|
53
|
+
setSelectedId(id);
|
|
54
|
+
console.log('Selected:', id);
|
|
55
|
+
}, []);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<view>
|
|
59
|
+
{items.map(item => (
|
|
60
|
+
<ItemCard
|
|
61
|
+
key={item.id}
|
|
62
|
+
item={item}
|
|
63
|
+
onSelect={handleSelect} // 函数引用不变
|
|
64
|
+
/>
|
|
65
|
+
))}
|
|
66
|
+
</view>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ❌ 不好的做法 - 每次渲染创建新函数
|
|
71
|
+
function ParentComponent({ items }: Props) {
|
|
72
|
+
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<view>
|
|
76
|
+
{items.map(item => (
|
|
77
|
+
<ItemCard
|
|
78
|
+
key={item.id}
|
|
79
|
+
item={item}
|
|
80
|
+
onSelect={(id) => setSelectedId(id)} // 每次创建新函数
|
|
81
|
+
/>
|
|
82
|
+
))}
|
|
83
|
+
</view>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 2. 列表渲染优化
|
|
89
|
+
|
|
90
|
+
#### 虚拟列表
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
// ✅ 好的做法 - 使用 Lynx list 组件的虚拟滚动
|
|
94
|
+
function VirtualList({ items }: { items: Item[] }) {
|
|
95
|
+
return (
|
|
96
|
+
<list
|
|
97
|
+
className="virtual-list"
|
|
98
|
+
list-type="single"
|
|
99
|
+
span-count={1}
|
|
100
|
+
scroll-orientation="vertical"
|
|
101
|
+
enable-nested-scroll={true}
|
|
102
|
+
// Lynx 会自动复用不可见的列表项
|
|
103
|
+
>
|
|
104
|
+
{items.map(item => (
|
|
105
|
+
<list-item key={item.id} item-key={item.id}>
|
|
106
|
+
<ItemCard item={item} />
|
|
107
|
+
</list-item>
|
|
108
|
+
))}
|
|
109
|
+
</list>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ❌ 不好的做法 - 渲染所有项
|
|
114
|
+
function AllItemsList({ items }: { items: Item[] }) {
|
|
115
|
+
// 如果有 1000+ 项,会严重影响性能
|
|
116
|
+
return (
|
|
117
|
+
<scroll-view>
|
|
118
|
+
{items.map(item => (
|
|
119
|
+
<ItemCard key={item.id} item={item} />
|
|
120
|
+
))}
|
|
121
|
+
</scroll-view>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### 分页加载
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
// ✅ 好的做法 - 分页加载大量数据
|
|
130
|
+
function InfiniteList() {
|
|
131
|
+
const [items, setItems] = useState<Item[]>([]);
|
|
132
|
+
const [page, setPage] = useState(1);
|
|
133
|
+
const [hasMore, setHasMore] = useState(true);
|
|
134
|
+
const [loading, setLoading] = useState(false);
|
|
135
|
+
|
|
136
|
+
const loadMore = async () => {
|
|
137
|
+
if (loading || !hasMore) return;
|
|
138
|
+
|
|
139
|
+
setLoading(true);
|
|
140
|
+
try {
|
|
141
|
+
const newItems = await fetchItems(page, 20);
|
|
142
|
+
setItems(prev => [...prev, ...newItems]);
|
|
143
|
+
setPage(prev => prev + 1);
|
|
144
|
+
setHasMore(newItems.length === 20);
|
|
145
|
+
} finally {
|
|
146
|
+
setLoading(false);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<list onScrollToLower={loadMore}>
|
|
152
|
+
{items.map(item => (
|
|
153
|
+
<list-item key={item.id}>
|
|
154
|
+
<ItemCard item={item} />
|
|
155
|
+
</list-item>
|
|
156
|
+
))}
|
|
157
|
+
{loading && <LoadingIndicator />}
|
|
158
|
+
</list>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 3. 图片优化
|
|
164
|
+
|
|
165
|
+
#### 懒加载
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
// ✅ 好的做法 - 图片懒加载
|
|
169
|
+
function LazyImage({ src, placeholder }: Props) {
|
|
170
|
+
const [loaded, setLoaded] = useState(false);
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<view className="lazy-image">
|
|
174
|
+
{!loaded && <image src={placeholder} className="lazy-image__placeholder" />}
|
|
175
|
+
<image
|
|
176
|
+
src={src}
|
|
177
|
+
className="lazy-image__actual"
|
|
178
|
+
style={{ display: loaded ? 'block' : 'none' }}
|
|
179
|
+
onLoad={() => setLoaded(true)}
|
|
180
|
+
onError={() => console.error('Failed to load image')}
|
|
181
|
+
/>
|
|
182
|
+
</view>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### 图片尺寸优化
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
// ✅ 好的做法 - 使用合适尺寸的图片
|
|
191
|
+
interface ImageProps {
|
|
192
|
+
src: string;
|
|
193
|
+
size: 'thumbnail' | 'medium' | 'large';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function OptimizedImage({ src, size }: ImageProps) {
|
|
197
|
+
const sizeParams = {
|
|
198
|
+
thumbnail: '?w=200&h=200&q=80',
|
|
199
|
+
medium: '?w=600&h=600&q=85',
|
|
200
|
+
large: '?w=1200&h=1200&q=90'
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
return <image src={`${src}${sizeParams[size]}`} />;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ❌ 不好的做法 - 加载原图后缩小
|
|
207
|
+
function UnoptimizedImage({ src }: Props) {
|
|
208
|
+
// 加载 5MB 的原图,然后显示为 100x100
|
|
209
|
+
return <image src={src} style={{ width: '100rpx', height: '100rpx' }} />;
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 🧠 内存优化
|
|
216
|
+
|
|
217
|
+
### 1. 及时清理资源
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
// ✅ 好的做法 - 清理定时器和订阅
|
|
221
|
+
function TimerComponent() {
|
|
222
|
+
const [count, setCount] = useState(0);
|
|
223
|
+
const timerRef = useRef<any>(null);
|
|
224
|
+
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
// 创建定时器
|
|
227
|
+
timerRef.current = setInterval(() => {
|
|
228
|
+
setCount(c => c + 1);
|
|
229
|
+
}, 1000);
|
|
230
|
+
|
|
231
|
+
// 清理函数
|
|
232
|
+
return () => {
|
|
233
|
+
if (timerRef.current) {
|
|
234
|
+
clearInterval(timerRef.current);
|
|
235
|
+
timerRef.current = null;
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}, []);
|
|
239
|
+
|
|
240
|
+
return <text>Count: {count}</text>;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ❌ 不好的做法 - 忘记清理
|
|
244
|
+
function TimerComponent() {
|
|
245
|
+
const [count, setCount] = useState(0);
|
|
246
|
+
|
|
247
|
+
useEffect(() => {
|
|
248
|
+
setInterval(() => {
|
|
249
|
+
setCount(c => c + 1);
|
|
250
|
+
}, 1000);
|
|
251
|
+
// 没有清理!组件卸载后定时器仍在运行
|
|
252
|
+
}, []);
|
|
253
|
+
|
|
254
|
+
return <text>Count: {count}</text>;
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 2. 避免内存泄漏
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
// ✅ 好的做法 - 检查组件是否已卸载
|
|
262
|
+
function DataFetcher() {
|
|
263
|
+
const [data, setData] = useState(null);
|
|
264
|
+
const mountedRef = useRef(true);
|
|
265
|
+
|
|
266
|
+
useEffect(() => {
|
|
267
|
+
const fetchData = async () => {
|
|
268
|
+
try {
|
|
269
|
+
const result = await api.getData();
|
|
270
|
+
// 只在组件仍挂载时更新状态
|
|
271
|
+
if (mountedRef.current) {
|
|
272
|
+
setData(result);
|
|
273
|
+
}
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.error(error);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
fetchData();
|
|
280
|
+
|
|
281
|
+
return () => {
|
|
282
|
+
mountedRef.current = false;
|
|
283
|
+
};
|
|
284
|
+
}, []);
|
|
285
|
+
|
|
286
|
+
return <view>{/* render data */}</view>;
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### 3. 大数据处理
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
// ✅ 好的做法 - 分批处理大数据
|
|
294
|
+
async function processBigData(data: any[]) {
|
|
295
|
+
const BATCH_SIZE = 100;
|
|
296
|
+
const results = [];
|
|
297
|
+
|
|
298
|
+
for (let i = 0; i < data.length; i += BATCH_SIZE) {
|
|
299
|
+
const batch = data.slice(i, i + BATCH_SIZE);
|
|
300
|
+
const processed = await processBatch(batch);
|
|
301
|
+
results.push(...processed);
|
|
302
|
+
|
|
303
|
+
// 让出主线程,避免阻塞 UI
|
|
304
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return results;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// ❌ 不好的做法 - 一次性处理所有数据
|
|
311
|
+
async function processBigData(data: any[]) {
|
|
312
|
+
// 如果数据量大,会阻塞 UI
|
|
313
|
+
return data.map(item => expensiveOperation(item));
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## 📦 包体积优化
|
|
320
|
+
|
|
321
|
+
### 1. 代码分割
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
// ✅ 好的做法 - 动态导入大组件
|
|
325
|
+
function HeavyFeature() {
|
|
326
|
+
const [Component, setComponent] = useState<any>(null);
|
|
327
|
+
|
|
328
|
+
useEffect(() => {
|
|
329
|
+
// 只在需要时加载
|
|
330
|
+
import('./HeavyComponent').then(module => {
|
|
331
|
+
setComponent(() => module.default);
|
|
332
|
+
});
|
|
333
|
+
}, []);
|
|
334
|
+
|
|
335
|
+
if (!Component) {
|
|
336
|
+
return <LoadingSpinner />;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return <Component />;
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
## 📱 启动性能优化
|
|
345
|
+
|
|
346
|
+
### 1. 延迟非关键代码
|
|
347
|
+
|
|
348
|
+
```tsx
|
|
349
|
+
// ✅ 好的做法 - 优先渲染关键内容
|
|
350
|
+
export default definePage({
|
|
351
|
+
aiMeta: { /* ... */ },
|
|
352
|
+
|
|
353
|
+
onShow() {
|
|
354
|
+
// 先显示页面骨架
|
|
355
|
+
this.showSkeleton = true;
|
|
356
|
+
|
|
357
|
+
// 延迟加载非关键数据
|
|
358
|
+
setTimeout(() => {
|
|
359
|
+
this.loadAnalytics();
|
|
360
|
+
this.loadRecommendations();
|
|
361
|
+
}, 1000);
|
|
362
|
+
|
|
363
|
+
// 优先加载关键数据
|
|
364
|
+
this.loadMainContent();
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
render() {
|
|
368
|
+
return this.showSkeleton ? <Skeleton /> : <Content />;
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### 2. 预加载关键资源
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
// ✅ 好的做法 - 预加载下一页可能需要的数据
|
|
377
|
+
function ListPage({ items }: Props) {
|
|
378
|
+
const [nextPageData, setNextPageData] = useState<Item[]>([]);
|
|
379
|
+
|
|
380
|
+
useEffect(() => {
|
|
381
|
+
// 预加载下一页数据
|
|
382
|
+
const prefetchNextPage = async () => {
|
|
383
|
+
try {
|
|
384
|
+
const data = await fetchItems(2);
|
|
385
|
+
setNextPageData(data);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
console.error('Prefetch failed:', error);
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
// 在用户可能操作前预加载
|
|
392
|
+
const timer = setTimeout(prefetchNextPage, 2000);
|
|
393
|
+
return () => clearTimeout(timer);
|
|
394
|
+
}, []);
|
|
395
|
+
|
|
396
|
+
return <ItemList items={items} />;
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## 🔗 相关文档
|
|
401
|
+
|
|
402
|
+
- [最佳实践](./best-practices.md) - 代码规范
|
|
403
|
+
- [组件开发完整指南](./component-development.md) - Page 和 Widget 开发
|
|
404
|
+
- [故障排查](./troubleshooting.md) - 常见问题
|