@doubao-apps/create 0.0.33 → 0.0.34

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.
Files changed (48) hide show
  1. package/dist/421.js +4 -4
  2. package/dist/cli.js +74 -66
  3. package/dist/index.d.ts +1 -2
  4. package/dist/template-empty/README.md +1 -1
  5. package/dist/template-empty/package.json +2 -2
  6. package/dist/template-starter/README.md +48 -169
  7. package/dist/template-starter/package.json +2 -2
  8. package/dist/template-starter/src/app.config.ts +2 -3
  9. package/dist/template-starter/src/pages/home/index.scss +38 -172
  10. package/dist/template-starter/src/pages/home/index.tsx +20 -78
  11. package/dist/template-starter/src/widgets/hello-world/index.scss +23 -0
  12. package/dist/template-starter/src/widgets/hello-world/index.tsx +29 -0
  13. package/package.json +6 -2
  14. package/dist/template-empty/AGENTS.md +0 -299
  15. package/dist/template-empty/references/examples/common-patterns.md +0 -589
  16. package/dist/template-empty/references/examples/component-basics.md +0 -526
  17. package/dist/template-empty/references/guides/best-practices.md +0 -571
  18. package/dist/template-empty/references/guides/component-development.md +0 -891
  19. package/dist/template-empty/references/guides/performance-optimization.md +0 -402
  20. package/dist/template-empty/references/guides/troubleshooting.md +0 -287
  21. package/dist/template-empty/references/reference/components-quick-ref.md +0 -103
  22. package/dist/template-empty/references/reference/framework-api-quick-ref.md +0 -550
  23. package/dist/template-empty/references/reference/open-api/README.md +0 -8
  24. package/dist/template-empty/references/reference/open-api.md +0 -11
  25. package/dist/template-empty/references/rules/dos-and-donts.md +0 -467
  26. package/dist/template-starter/AGENTS.md +0 -299
  27. package/dist/template-starter/debug-scene/render-home-page-full.json +0 -6
  28. package/dist/template-starter/debug-scene/render-home-page.json +0 -5
  29. package/dist/template-starter/debug-scene/render-react-lynx-page-full.json +0 -6
  30. package/dist/template-starter/references/examples/common-patterns.md +0 -589
  31. package/dist/template-starter/references/examples/component-basics.md +0 -526
  32. package/dist/template-starter/references/guides/best-practices.md +0 -571
  33. package/dist/template-starter/references/guides/component-development.md +0 -891
  34. package/dist/template-starter/references/guides/performance-optimization.md +0 -402
  35. package/dist/template-starter/references/guides/troubleshooting.md +0 -287
  36. package/dist/template-starter/references/reference/components-quick-ref.md +0 -103
  37. package/dist/template-starter/references/reference/framework-api-quick-ref.md +0 -550
  38. package/dist/template-starter/references/reference/open-api/README.md +0 -8
  39. package/dist/template-starter/references/reference/open-api.md +0 -11
  40. package/dist/template-starter/references/rules/dos-and-donts.md +0 -467
  41. package/dist/template-starter/src/pages/applet/index.scss +0 -279
  42. package/dist/template-starter/src/pages/applet/index.tsx +0 -78
  43. package/dist/template-starter/src/pages/lynx/index.scss +0 -249
  44. package/dist/template-starter/src/pages/lynx/index.tsx +0 -78
  45. package/dist/template-starter/src/pages/react-lynx/index.scss +0 -335
  46. package/dist/template-starter/src/pages/react-lynx/index.tsx +0 -132
  47. package/dist/template-starter/src/widgets/weather-card/index.scss +0 -272
  48. package/dist/template-starter/src/widgets/weather-card/index.tsx +0 -193
@@ -1,589 +0,0 @@
1
- # 常用开发模式
2
-
3
- API 集成、状态管理、页面导航的常用开发模式和最佳实践。
4
-
5
- ---
6
-
7
- ## 📋 目录
8
-
9
- 1. [API 集成模式](#api-集成模式)
10
- 2. [状态管理模式](#状态管理模式)
11
- 3. [页面导航模式](#页面导航模式)
12
-
13
- ---
14
-
15
- ## 🌐 API 集成模式
16
-
17
- ### Bridge API 调用
18
-
19
- 使用 Bridge API 访问系统能力(网络请求、存储、设备功能等)。
20
-
21
- ```tsx
22
- import { useState } from '@doubao-apps/framework';
23
- import { getLocation, getPhoneNumber, request } from '@doubao-apps/framework/api';
24
-
25
- function DataFetchExample() {
26
- const [data, setData] = useState(null);
27
- const [loading, setLoading] = useState(false);
28
- const [error, setError] = useState(null);
29
-
30
- // 1. 网络请求
31
- const fetchData = async () => {
32
- try {
33
- setLoading(true);
34
- setError(null);
35
-
36
- const response = await request({
37
- url: 'https://api.example.com/data',
38
- method: 'GET',
39
- header: {
40
- 'Content-Type': 'application/json'
41
- }
42
- });
43
-
44
- setData(response.data);
45
- } catch (err) {
46
- setError(err.message);
47
- } finally {
48
- setLoading(false);
49
- }
50
- };
51
-
52
- // 2. 获取手机号(需要用户授权)
53
- const fetchPhoneNumber = async () => {
54
- try {
55
- const result = await getPhoneNumber();
56
- console.log('手机号信息:', result);
57
- } catch (err) {
58
- console.error('获取手机号失败:', err);
59
- }
60
- };
61
-
62
- // 3. 获取地理位置
63
- const fetchLocation = async () => {
64
- try {
65
- const location = await getLocation();
66
- console.log('位置:', location);
67
- } catch (err) {
68
- console.error('获取位置失败:', err);
69
- }
70
- };
71
-
72
- return (
73
- <view>
74
- <button onClick={fetchData}>获取数据</button>
75
- <button onClick={fetchPhoneNumber}>获取手机号</button>
76
- <button onClick={fetchLocation}>获取位置</button>
77
- {loading && <text>加载中...</text>}
78
- {error && <text>错误: {error}</text>}
79
- {data && <text>数据: {JSON.stringify(data)}</text>}
80
- </view>
81
- );
82
- }
83
- ```
84
-
85
- ### POST 请求示例
86
-
87
- ```tsx
88
- const submitForm = async (formData: any) => {
89
- try {
90
- const response = await request({
91
- url: 'https://api.example.com/submit',
92
- method: 'POST',
93
- header: {
94
- 'Content-Type': 'application/json'
95
- },
96
- data: formData
97
- });
98
-
99
- if (response.statusCode >= 200 && response.statusCode < 300) {
100
- console.log('提交成功');
101
- }
102
- } catch (err) {
103
- console.error('提交失败:', err);
104
- }
105
- };
106
- ```
107
-
108
- ### 请求拦截和错误处理
109
-
110
- ```tsx
111
- interface ApiError {
112
- code: number;
113
- message: string;
114
- }
115
-
116
- async function apiRequest<T>(url: string, options: any): Promise<T> {
117
- try {
118
- const response = await request({
119
- url,
120
- ...options
121
- });
122
-
123
- // 检查响应状态
124
- if (response.statusCode >= 400) {
125
- throw {
126
- code: response.statusCode,
127
- message: response.data?.message || '请求失败'
128
- } as ApiError;
129
- }
130
-
131
- return response.data as T;
132
- } catch (err) {
133
- // 统一错误处理
134
- if (err.code === 401) {
135
- console.error('未授权,请登录');
136
- } else if (err.code === 404) {
137
- console.error('资源不存在');
138
- } else {
139
- console.error('请求错误:', err.message);
140
- }
141
- throw err;
142
- }
143
- }
144
-
145
- // 使用示例
146
- async function fetchUserData(userId: string) {
147
- try {
148
- const data = await apiRequest<User>(`/api/users/${userId}`, {
149
- method: 'GET'
150
- });
151
- return data;
152
- } catch (err) {
153
- // 业务逻辑错误处理
154
- return null;
155
- }
156
- }
157
- ```
158
-
159
- ---
160
-
161
- ## 📊 状态管理模式
162
-
163
- ### 1. 本地状态 (useState)
164
-
165
- 适用于组件内部状态管理。
166
-
167
- ```tsx
168
- import { useState } from '@doubao-apps/framework';
169
-
170
- function Counter() {
171
- const [count, setCount] = useState(0);
172
-
173
- return (
174
- <view>
175
- <text>计数: {count}</text>
176
- <button onClick={() => setCount(count + 1)}>增加</button>
177
- <button onClick={() => setCount(count - 1)}>减少</button>
178
- <button onClick={() => setCount(0)}>重置</button>
179
- </view>
180
- );
181
- }
182
- ```
183
-
184
- ### 2. 副作用管理 (useEffect)
185
-
186
- 适用于数据获取、订阅、定时器等副作用。
187
-
188
- ```tsx
189
- import { useState, useEffect } from '@doubao-apps/framework';
190
- import { request } from '@doubao-apps/framework/api';
191
-
192
- function DataLoader() {
193
- const [data, setData] = useState(null);
194
-
195
- useEffect(() => {
196
- // 数据获取
197
- const fetchData = async () => {
198
- try {
199
- const response = await request({
200
- url: '/api/data',
201
- method: 'GET'
202
- });
203
- setData(response.data);
204
- } catch (error) {
205
- console.error('获取数据失败:', error);
206
- }
207
- };
208
-
209
- fetchData();
210
-
211
- // 清理函数
212
- return () => {
213
- console.log('组件卸载,清理资源');
214
- };
215
- }, []); // 空依赖数组表示只在挂载时执行一次
216
-
217
- return <view>{data ? <text>{data}</text> : <text>加载中...</text>}</view>;
218
- }
219
- ```
220
-
221
- ### 3. 复杂状态 (useReducer)
222
-
223
- 适用于复杂状态逻辑。
224
-
225
- ```tsx
226
- import { useReducer } from '@doubao-apps/framework';
227
-
228
- // 定义状态和动作类型
229
- interface State {
230
- count: number;
231
- step: number;
232
- }
233
-
234
- type Action =
235
- | { type: 'increment' }
236
- | { type: 'decrement' }
237
- | { type: 'setStep'; step: number }
238
- | { type: 'reset' };
239
-
240
- // Reducer 函数
241
- function reducer(state: State, action: Action): State {
242
- switch (action.type) {
243
- case 'increment':
244
- return { ...state, count: state.count + state.step };
245
- case 'decrement':
246
- return { ...state, count: state.count - state.step };
247
- case 'setStep':
248
- return { ...state, step: action.step };
249
- case 'reset':
250
- return { count: 0, step: 1 };
251
- default:
252
- return state;
253
- }
254
- }
255
-
256
- function ComplexCounter() {
257
- const [state, dispatch] = useReducer(reducer, { count: 0, step: 1 });
258
-
259
- return (
260
- <view>
261
- <text>计数: {state.count}</text>
262
- <text>步长: {state.step}</text>
263
- <button onClick={() => dispatch({ type: 'increment' })}>增加</button>
264
- <button onClick={() => dispatch({ type: 'decrement' })}>减少</button>
265
- <button onClick={() => dispatch({ type: 'setStep', step: 5 })}>
266
- 设置步长为 5
267
- </button>
268
- <button onClick={() => dispatch({ type: 'reset' })}>重置</button>
269
- </view>
270
- );
271
- }
272
- ```
273
-
274
- ### 4. 跨组件状态共享 (Context)
275
-
276
- 适用于全局或跨组件状态。
277
-
278
- ```tsx
279
- import { createContext, useContext, useState } from '@doubao-apps/framework';
280
-
281
- // 1. 创建 Context
282
- interface ThemeContextValue {
283
- theme: 'light' | 'dark';
284
- toggleTheme: () => void;
285
- }
286
-
287
- const ThemeContext = createContext<ThemeContextValue | null>(null);
288
-
289
- // 2. Provider 组件
290
- function ThemeProvider({ children }) {
291
- const [theme, setTheme] = useState<'light' | 'dark'>('light');
292
-
293
- const toggleTheme = () => {
294
- setTheme(prev => (prev === 'light' ? 'dark' : 'light'));
295
- };
296
-
297
- return (
298
- <ThemeContext.Provider value={{ theme, toggleTheme }}>
299
- {children}
300
- </ThemeContext.Provider>
301
- );
302
- }
303
-
304
- // 3. 使用 Context
305
- function ThemedButton() {
306
- const context = useContext(ThemeContext);
307
- if (!context) throw new Error('必须在 ThemeProvider 内使用');
308
-
309
- const { theme, toggleTheme } = context;
310
-
311
- return (
312
- <button
313
- className={theme === 'light' ? 'light-button' : 'dark-button'}
314
- onClick={toggleTheme}
315
- >
316
- 切换主题
317
- </button>
318
- );
319
- }
320
-
321
- // 4. 应用中使用
322
- function App() {
323
- return (
324
- <ThemeProvider>
325
- <view>
326
- <ThemedButton />
327
- </view>
328
- </ThemeProvider>
329
- );
330
- }
331
- ```
332
-
333
- ### 5. 自定义 Hook
334
-
335
- 封装可复用的状态逻辑。
336
-
337
- ```tsx
338
- import { useState, useEffect } from '@doubao-apps/framework';
339
- import { request } from '@doubao-apps/framework/api';
340
-
341
- // 自定义 Hook:数据获取
342
- function useFetch<T>(url: string) {
343
- const [data, setData] = useState<T | null>(null);
344
- const [loading, setLoading] = useState(true);
345
- const [error, setError] = useState<string | null>(null);
346
-
347
- useEffect(() => {
348
- const fetchData = async () => {
349
- try {
350
- setLoading(true);
351
- setError(null);
352
- const response = await request({ url, method: 'GET' });
353
- setData(response.data as T);
354
- } catch (err) {
355
- setError(err.message);
356
- } finally {
357
- setLoading(false);
358
- }
359
- };
360
-
361
- fetchData();
362
- }, [url]);
363
-
364
- return { data, loading, error };
365
- }
366
-
367
- // 使用自定义 Hook
368
- function UserProfile({ userId }) {
369
- const { data: user, loading, error } = useFetch<User>(`/api/users/${userId}`);
370
-
371
- if (loading) return <text>加载中...</text>;
372
- if (error) return <text>错误: {error}</text>;
373
- if (!user) return <text>无数据</text>;
374
-
375
- return (
376
- <view>
377
- <text>{user.name}</text>
378
- <text>{user.email}</text>
379
- </view>
380
- );
381
- }
382
- ```
383
-
384
- ---
385
-
386
- ## 🧭 页面导航模式
387
-
388
- ### 1. 打开新页面
389
-
390
- ```tsx
391
- import { navigateTo, redirectTo, reLaunch } from '@doubao-apps/framework/api';
392
-
393
- // 保留当前页面,打开详情页
394
- function openFullPage() {
395
- navigateTo({
396
- url: 'user-profile?userId=12345'
397
- });
398
- }
399
-
400
- // 替换当前页面
401
- function openSettingsPage() {
402
- redirectTo({
403
- url: 'settings'
404
- });
405
- }
406
-
407
- // 清空页面栈并回到首页
408
- function relaunchHome() {
409
- reLaunch({
410
- url: 'home'
411
- });
412
- }
413
- ```
414
-
415
- 这里的 `url` 直接使用目标页面的 `pageId`。显式配置时取 `src/app.config.ts` 中对应 page 的 `id`;不配置时取入口目录名,例如
416
- `src/pages/detail/index.tsx` 默认为 `detail`。如需传参,可继续拼接 query string。
417
-
418
- ### 2. 页面间传参
419
-
420
- ```tsx
421
- import { navigateTo } from '@doubao-apps/framework/api';
422
-
423
- function buildPageUrl(pageId: string, params: Record<string, string | number | boolean>) {
424
- const query = Object.entries(params)
425
- .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
426
- .join('&');
427
-
428
- return query ? `${pageId}?${query}` : pageId;
429
- }
430
-
431
- // 发送方
432
- function navigateWithParams() {
433
- navigateTo({
434
- url: buildPageUrl('detail-page', {
435
- id: '123',
436
- name: '商品名称',
437
- price: 99.99
438
- })
439
- });
440
- }
441
-
442
- // 接收方 (detail-page)
443
- import { getViewData } from '@doubao-apps/framework';
444
-
445
- interface DetailPageData {
446
- id: string;
447
- name: string;
448
- price: number;
449
- }
450
-
451
- export default definePage({
452
- render() {
453
- // getViewData() 直接返回传入页面的最终对象
454
- const { id, name, price } = getViewData<DetailPageData>();
455
-
456
- return (
457
- <view>
458
- <text>ID: {id}</text>
459
- <text>名称: {name}</text>
460
- <text>价格: {price}</text>
461
- </view>
462
- );
463
- }
464
- });
465
- ```
466
-
467
- ### 3. 返回上一页
468
-
469
- ```tsx
470
- import { navigateBack } from '@doubao-apps/framework/api';
471
-
472
- function closeCurrentPage() {
473
- navigateBack();
474
- }
475
- ```
476
-
477
- ### 4. 页面栈管理
478
-
479
- ```tsx
480
- import { navigateBack } from '@doubao-apps/framework/api';
481
-
482
- // 场景 1: 返回上一页
483
- function goBack() {
484
- navigateBack();
485
- }
486
-
487
- // 场景 2: 返回多级页面
488
- function goBackTwoPages() {
489
- navigateBack({ delta: 2 });
490
- }
491
- ```
492
-
493
- ### 5. 页面生命周期导航处理
494
-
495
- ```tsx
496
- export default definePage({
497
- onShow() {
498
- // 页面显示时调用(包括从其他页面返回)
499
- console.log('页面显示');
500
- // 可以在这里刷新数据
501
- },
502
- onHide() {
503
- // 页面隐藏时调用
504
- console.log('页面隐藏');
505
- // 可以在这里暂停视频、保存草稿等
506
- },
507
- onDestroy() {
508
- // 页面销毁时调用
509
- console.log('页面销毁');
510
- // 清理资源、取消订阅等
511
- },
512
- render() {
513
- return <view>页面内容</view>;
514
- }
515
- });
516
- ```
517
-
518
- ### 6. 九宫格页面导航
519
-
520
- ```tsx
521
- import { navigateTo } from '@doubao-apps/framework/api';
522
-
523
- // 打开九宫格页面
524
- function openGridPage() {
525
- navigateTo({
526
- url: 'app-grid'
527
- });
528
- }
529
-
530
- // 九宫格页面定义
531
- export default definePage({
532
- render() {
533
- const apps = [
534
- { id: 'app1', name: '应用1', icon: '🎯' },
535
- { id: 'app2', name: '应用2', icon: '📱' },
536
- { id: 'app3', name: '应用3', icon: '⚡' }
537
- ];
538
-
539
- return (
540
- <view className="grid-container">
541
- {apps.map(app => (
542
- <view
543
- key={app.id}
544
- className="grid-item"
545
- onClick={() => navigateTo({ url: app.id })}
546
- >
547
- <text className="icon">{app.icon}</text>
548
- <text className="name">{app.name}</text>
549
- </view>
550
- ))}
551
- </view>
552
- );
553
- }
554
- });
555
- ```
556
-
557
- ---
558
-
559
- ## 🎯 最佳实践
560
-
561
- ### API 集成
562
-
563
- 1. **统一错误处理** - 封装 API 请求函数,统一处理错误
564
- 2. **请求取消** - 组件卸载时取消未完成的请求
565
- 3. **缓存策略** - 合理使用缓存减少网络请求
566
- 4. **加载状态** - 始终提供加载和错误状态反馈
567
-
568
- ### 状态管理
569
-
570
- 1. **最小化状态** - 只存储必要的状态,能计算的不存储
571
- 2. **状态提升** - 共享状态提升到最近的公共父组件
572
- 3. **避免过度渲染** - 使用 useMemo、useCallback 优化性能
573
- 4. **状态持久化** - 重要状态考虑持久化到本地存储
574
-
575
- ### 页面导航
576
-
577
- 1. **合理的页面层级** - 避免页面栈过深(建议不超过 3-4 层)
578
- 2. **参数验证** - 接收页面参数时进行验证和默认值处理
579
- 3. **返回结果** - 关闭页面时返回必要的结果数据
580
- 4. **生命周期管理** - 合理使用生命周期钩子管理资源
581
-
582
- ---
583
-
584
- ## 📚 延伸阅读
585
-
586
- - **组件基础** → [./component-basics.md](./component-basics.md)
587
- - **组件开发完整指南** → [../guides/component-development.md](../guides/component-development.md)
588
- - **API 参考** → [../reference/framework-api-quick-ref.md](../reference/framework-api-quick-ref.md)
589
- - **最佳实践** → [../guides/best-practices.md](../guides/best-practices.md)