@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.
- package/dist/421.js +4 -4
- package/dist/cli.js +74 -66
- package/dist/index.d.ts +1 -2
- package/dist/template-empty/README.md +1 -1
- package/dist/template-empty/package.json +2 -2
- package/dist/template-starter/README.md +48 -169
- package/dist/template-starter/package.json +2 -2
- package/dist/template-starter/src/app.config.ts +2 -3
- package/dist/template-starter/src/pages/home/index.scss +38 -172
- package/dist/template-starter/src/pages/home/index.tsx +20 -78
- package/dist/template-starter/src/widgets/hello-world/index.scss +23 -0
- package/dist/template-starter/src/widgets/hello-world/index.tsx +29 -0
- package/package.json +6 -2
- package/dist/template-empty/AGENTS.md +0 -299
- package/dist/template-empty/references/examples/common-patterns.md +0 -589
- package/dist/template-empty/references/examples/component-basics.md +0 -526
- package/dist/template-empty/references/guides/best-practices.md +0 -571
- package/dist/template-empty/references/guides/component-development.md +0 -891
- package/dist/template-empty/references/guides/performance-optimization.md +0 -402
- package/dist/template-empty/references/guides/troubleshooting.md +0 -287
- package/dist/template-empty/references/reference/components-quick-ref.md +0 -103
- package/dist/template-empty/references/reference/framework-api-quick-ref.md +0 -550
- package/dist/template-empty/references/reference/open-api/README.md +0 -8
- package/dist/template-empty/references/reference/open-api.md +0 -11
- package/dist/template-empty/references/rules/dos-and-donts.md +0 -467
- package/dist/template-starter/AGENTS.md +0 -299
- package/dist/template-starter/debug-scene/render-home-page-full.json +0 -6
- package/dist/template-starter/debug-scene/render-home-page.json +0 -5
- package/dist/template-starter/debug-scene/render-react-lynx-page-full.json +0 -6
- package/dist/template-starter/references/examples/common-patterns.md +0 -589
- package/dist/template-starter/references/examples/component-basics.md +0 -526
- package/dist/template-starter/references/guides/best-practices.md +0 -571
- package/dist/template-starter/references/guides/component-development.md +0 -891
- package/dist/template-starter/references/guides/performance-optimization.md +0 -402
- package/dist/template-starter/references/guides/troubleshooting.md +0 -287
- package/dist/template-starter/references/reference/components-quick-ref.md +0 -103
- package/dist/template-starter/references/reference/framework-api-quick-ref.md +0 -550
- package/dist/template-starter/references/reference/open-api/README.md +0 -8
- package/dist/template-starter/references/reference/open-api.md +0 -11
- package/dist/template-starter/references/rules/dos-and-donts.md +0 -467
- package/dist/template-starter/src/pages/applet/index.scss +0 -279
- package/dist/template-starter/src/pages/applet/index.tsx +0 -78
- package/dist/template-starter/src/pages/lynx/index.scss +0 -249
- package/dist/template-starter/src/pages/lynx/index.tsx +0 -78
- package/dist/template-starter/src/pages/react-lynx/index.scss +0 -335
- package/dist/template-starter/src/pages/react-lynx/index.tsx +0 -132
- package/dist/template-starter/src/widgets/weather-card/index.scss +0 -272
- package/dist/template-starter/src/widgets/weather-card/index.tsx +0 -193
|
@@ -1,467 +0,0 @@
|
|
|
1
|
-
# 开发规则 - Do's and Don'ts
|
|
2
|
-
|
|
3
|
-
Doubao Apps SDK 框架的开发规则和最佳实践。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## ✅ 推荐做法(Do's)
|
|
8
|
-
|
|
9
|
-
### 项目管理
|
|
10
|
-
|
|
11
|
-
#### ✅ 使用 pnpm 包管理器
|
|
12
|
-
```bash
|
|
13
|
-
# 推荐
|
|
14
|
-
pnpm install
|
|
15
|
-
pnpm add @doubao-apps/framework
|
|
16
|
-
|
|
17
|
-
# 不推荐(除非项目已使用 npm)
|
|
18
|
-
npm install
|
|
19
|
-
npm install @doubao-apps/framework
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
### 组件开发
|
|
24
|
-
|
|
25
|
-
#### ✅ 在 app.config.ts 配置 App 元信息
|
|
26
|
-
```ts
|
|
27
|
-
import { defineAppConfig } from '@doubao-apps/kit';
|
|
28
|
-
|
|
29
|
-
export default defineAppConfig({
|
|
30
|
-
appId: 'com.example.my-doubao-app',
|
|
31
|
-
name: '我的豆包应用'
|
|
32
|
-
});
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
#### ✅ 需要稳定首页时在 app.config.ts 明确入口
|
|
36
|
-
```ts
|
|
37
|
-
// ✅ pages 数组第一项会作为首页(appletEntry)
|
|
38
|
-
import { defineAppConfig } from '@doubao-apps/kit';
|
|
39
|
-
|
|
40
|
-
export default defineAppConfig({
|
|
41
|
-
appId: 'com.example.my-doubao-app',
|
|
42
|
-
name: '我的豆包应用',
|
|
43
|
-
pages: [
|
|
44
|
-
{
|
|
45
|
-
entry: 'pages/home/index',
|
|
46
|
-
id: 'home',
|
|
47
|
-
title: '首页',
|
|
48
|
-
description: '应用默认打开的页面'
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
});
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
一级页面目录不写进 `pages` 也会自动发现;如果首页不是历史默认的 `index`,或需要固定首页顺序,建议显式配置 `pages`
|
|
55
|
-
数组第一项。
|
|
56
|
-
|
|
57
|
-
#### ✅ 需要补充展示信息时在 app.config.ts 定义 metadata
|
|
58
|
-
```ts
|
|
59
|
-
// ✅ 好的做法
|
|
60
|
-
import { defineAppConfig } from '@doubao-apps/kit';
|
|
61
|
-
|
|
62
|
-
export default defineAppConfig({
|
|
63
|
-
appId: 'com.example.my-doubao-app',
|
|
64
|
-
name: '我的豆包应用',
|
|
65
|
-
pages: [
|
|
66
|
-
{
|
|
67
|
-
entry: 'pages/user-profile/index',
|
|
68
|
-
id: 'user-profile',
|
|
69
|
-
title: '用户资料',
|
|
70
|
-
description: '展示和编辑用户个人资料'
|
|
71
|
-
}
|
|
72
|
-
]
|
|
73
|
-
});
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
```ts
|
|
77
|
-
// ❌ 不好的做法:缺少 title、description 等信息
|
|
78
|
-
import { defineAppConfig } from '@doubao-apps/kit';
|
|
79
|
-
|
|
80
|
-
export default defineAppConfig({
|
|
81
|
-
appId: 'com.example.my-doubao-app',
|
|
82
|
-
name: '我的豆包应用',
|
|
83
|
-
pages: [
|
|
84
|
-
{
|
|
85
|
-
entry: 'pages/user-profile/index',
|
|
86
|
-
id: 'page1'
|
|
87
|
-
}
|
|
88
|
-
]
|
|
89
|
-
});
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
#### ✅ 多级目录必须显式声明 entry
|
|
93
|
-
```ts
|
|
94
|
-
// src/pages/account/demo/index.tsx
|
|
95
|
-
// src/widgets/order/detail/index.tsx
|
|
96
|
-
import { defineAppConfig } from '@doubao-apps/kit';
|
|
97
|
-
|
|
98
|
-
export default defineAppConfig({
|
|
99
|
-
appId: 'com.example.my-doubao-app',
|
|
100
|
-
name: '我的豆包应用',
|
|
101
|
-
pages: [
|
|
102
|
-
// 只声明入口、不补 metadata 时,可以直接写字符串
|
|
103
|
-
'pages/account/demo/index',
|
|
104
|
-
{
|
|
105
|
-
entry: 'pages/account/settings/index',
|
|
106
|
-
id: 'account-settings',
|
|
107
|
-
title: '账号设置页'
|
|
108
|
-
}
|
|
109
|
-
],
|
|
110
|
-
widgets: [
|
|
111
|
-
'widgets/order/detail/index',
|
|
112
|
-
{
|
|
113
|
-
entry: 'widgets/order/summary/index',
|
|
114
|
-
id: 'order-summary',
|
|
115
|
-
name: '订单摘要卡片'
|
|
116
|
-
}
|
|
117
|
-
]
|
|
118
|
-
});
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
如果不配置 `id`,默认取入口最后一级目录名:`pages/account/demo/index` 默认为 `demo`,`widgets/order/detail/index`
|
|
122
|
-
默认为 `detail`。
|
|
123
|
-
|
|
124
|
-
#### ✅ 分离样式文件
|
|
125
|
-
```tsx
|
|
126
|
-
// ✅ 好的做法
|
|
127
|
-
// index.tsx
|
|
128
|
-
import './index.scss';
|
|
129
|
-
|
|
130
|
-
export default definePage({
|
|
131
|
-
// ...
|
|
132
|
-
});
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
```scss
|
|
136
|
-
// index.scss
|
|
137
|
-
.container {
|
|
138
|
-
padding: 16px;
|
|
139
|
-
background: #fff;
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
```tsx
|
|
144
|
-
// ❌ 不好的做法
|
|
145
|
-
export default definePage({
|
|
146
|
-
render() {
|
|
147
|
-
return (
|
|
148
|
-
<view style={{ padding: '16px', background: '#fff' }}>
|
|
149
|
-
内容
|
|
150
|
-
</view>
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
#### ✅ 使用 TypeScript 类型定义
|
|
157
|
-
```tsx
|
|
158
|
-
// ✅ 好的做法
|
|
159
|
-
interface UserInfo {
|
|
160
|
-
name: string;
|
|
161
|
-
age: number;
|
|
162
|
-
avatar?: string;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export default defineWidget({
|
|
166
|
-
render() {
|
|
167
|
-
const viewData = getViewData<UserInfo>();
|
|
168
|
-
return <view>{viewData.name}</view>;
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
```ts
|
|
174
|
-
// ✅ 把 metadata 写到 src/app.config.ts
|
|
175
|
-
import { defineAppConfig } from '@doubao-apps/kit';
|
|
176
|
-
|
|
177
|
-
export default defineAppConfig({
|
|
178
|
-
appId: 'com.example.my-doubao-app',
|
|
179
|
-
name: '我的豆包应用',
|
|
180
|
-
widgets: [
|
|
181
|
-
{
|
|
182
|
-
entry: 'widgets/user-card/index',
|
|
183
|
-
id: 'user-card',
|
|
184
|
-
name: '用户卡片',
|
|
185
|
-
description: '用户信息卡片'
|
|
186
|
-
}
|
|
187
|
-
]
|
|
188
|
-
});
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
```tsx
|
|
192
|
-
// ❌ 不好的做法
|
|
193
|
-
export default defineWidget({
|
|
194
|
-
render() {
|
|
195
|
-
const viewData = getViewData<any>(); // 使用 any 类型,失去类型检查
|
|
196
|
-
return <view>{viewData.name}</view>;
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
#### ✅ 使用生命周期钩子
|
|
202
|
-
```tsx
|
|
203
|
-
// ✅ 好的做法
|
|
204
|
-
export default definePage({
|
|
205
|
-
onShow() {
|
|
206
|
-
console.log('Page shown');
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
onHide() {
|
|
210
|
-
console.log('Page hidden');
|
|
211
|
-
},
|
|
212
|
-
|
|
213
|
-
onDestroy() {
|
|
214
|
-
console.log('Page destroyed');
|
|
215
|
-
},
|
|
216
|
-
|
|
217
|
-
render() {
|
|
218
|
-
return <view>内容</view>;
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
#### ✅ 错误处理和边界情况
|
|
225
|
-
```tsx
|
|
226
|
-
// ✅ 好的做法
|
|
227
|
-
export default defineWidget({
|
|
228
|
-
render() {
|
|
229
|
-
const viewData = getViewData<{ items: string[] }>();
|
|
230
|
-
// 处理空数据
|
|
231
|
-
if (!viewData.items || viewData.items.length === 0) {
|
|
232
|
-
return <view>暂无数据</view>;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return (
|
|
236
|
-
<view>
|
|
237
|
-
{viewData.items.map((item, index) => (
|
|
238
|
-
<view key={index}>{item}</view>
|
|
239
|
-
))}
|
|
240
|
-
</view>
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
```tsx
|
|
247
|
-
// ❌ 不好的做法
|
|
248
|
-
export default defineWidget({
|
|
249
|
-
render() {
|
|
250
|
-
const viewData = getViewData<any>();
|
|
251
|
-
// 没有检查 viewData.items 是否存在
|
|
252
|
-
return (
|
|
253
|
-
<view>
|
|
254
|
-
{viewData.items.map(item => <view>{item}</view>)}
|
|
255
|
-
</view>
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
## ❌ 禁止做法(Don'ts)
|
|
264
|
-
|
|
265
|
-
### 样式相关
|
|
266
|
-
|
|
267
|
-
#### ❌ 内联样式长度值必须带单位
|
|
268
|
-
|
|
269
|
-
Lynx CSS encoder 要求:**所有 CSS 长度值必须显式带单位**,裸数字(无单位)会触发运行时错误 `CSS length need units (except 0)`。
|
|
270
|
-
|
|
271
|
-
```tsx
|
|
272
|
-
// ❌ 错误:裸数字(无单位)
|
|
273
|
-
<view style={{ width: 100, height: 56, fontSize: 14 }} />
|
|
274
|
-
|
|
275
|
-
// ✅ 正确:带单位字符串
|
|
276
|
-
<view style={{ width: '100px', height: '56px', fontSize: '14px' }} />
|
|
277
|
-
|
|
278
|
-
// ✅ 例外:以下属性可以使用裸数字(无单位)
|
|
279
|
-
// flex, opacity, zIndex, fontWeight, aspectRatio
|
|
280
|
-
<view style={{ flex: 1, opacity: 0.5, zIndex: 10 }} />
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
#### ❌ 不写内联样式
|
|
284
|
-
```tsx
|
|
285
|
-
// ❌ 错误
|
|
286
|
-
export default definePage({
|
|
287
|
-
render() {
|
|
288
|
-
return (
|
|
289
|
-
<view style={{ padding: 16, background: '#fff' }}>
|
|
290
|
-
内容
|
|
291
|
-
</view>
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
```tsx
|
|
298
|
-
// ✅ 正确
|
|
299
|
-
import './index.scss';
|
|
300
|
-
|
|
301
|
-
export default definePage({
|
|
302
|
-
render() {
|
|
303
|
-
return (
|
|
304
|
-
<view className="container">
|
|
305
|
-
内容
|
|
306
|
-
</view>
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### 异步操作
|
|
313
|
-
|
|
314
|
-
#### ❌ 不在 render 中发起请求
|
|
315
|
-
```tsx
|
|
316
|
-
// ❌ 错误 - 每次渲染都会发请求
|
|
317
|
-
export default definePage({
|
|
318
|
-
render() {
|
|
319
|
-
fetch('/api/data').then(data => {
|
|
320
|
-
// 处理数据
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
return <view>内容</view>;
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
```tsx
|
|
329
|
-
// ✅ 推荐 - 使用 Hook 管理请求和状态
|
|
330
|
-
import { useEffect, useState } from '@doubao-apps/framework';
|
|
331
|
-
|
|
332
|
-
function UserPage() {
|
|
333
|
-
const [userData, setUserData] = useState<{ name?: string } | null>(null);
|
|
334
|
-
|
|
335
|
-
useEffect(() => {
|
|
336
|
-
fetch('/api/data')
|
|
337
|
-
.then(res => res.json())
|
|
338
|
-
.then(data => {
|
|
339
|
-
setUserData(data);
|
|
340
|
-
});
|
|
341
|
-
}, []);
|
|
342
|
-
|
|
343
|
-
return <view>{userData?.name}</view>;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
export default definePage({
|
|
347
|
-
render() {
|
|
348
|
-
return <UserPage />;
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
### 组件结构
|
|
354
|
-
|
|
355
|
-
#### ❌ 不过度嵌套组件
|
|
356
|
-
```tsx
|
|
357
|
-
// ❌ 错误 - 过度嵌套
|
|
358
|
-
export default definePage({
|
|
359
|
-
render() {
|
|
360
|
-
return (
|
|
361
|
-
<view>
|
|
362
|
-
<view>
|
|
363
|
-
<view>
|
|
364
|
-
<view>
|
|
365
|
-
<view>
|
|
366
|
-
<view>
|
|
367
|
-
内容
|
|
368
|
-
</view>
|
|
369
|
-
</view>
|
|
370
|
-
</view>
|
|
371
|
-
</view>
|
|
372
|
-
</view>
|
|
373
|
-
</view>
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
```tsx
|
|
380
|
-
// ✅ 正确 - 扁平结构
|
|
381
|
-
export default definePage({
|
|
382
|
-
render() {
|
|
383
|
-
return (
|
|
384
|
-
<view className="page">
|
|
385
|
-
<view className="header">头部</view>
|
|
386
|
-
<view className="content">内容</view>
|
|
387
|
-
<view className="footer">底部</view>
|
|
388
|
-
</view>
|
|
389
|
-
);
|
|
390
|
-
}
|
|
391
|
-
});
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### 类型使用
|
|
395
|
-
|
|
396
|
-
#### ❌ 不忽略 TypeScript 类型
|
|
397
|
-
```tsx
|
|
398
|
-
// ❌ 错误
|
|
399
|
-
export default defineWidget({
|
|
400
|
-
render() {
|
|
401
|
-
const viewData = getViewData<any>();
|
|
402
|
-
// @ts-ignore
|
|
403
|
-
return <view>{viewData.unknownProperty}</view>;
|
|
404
|
-
}
|
|
405
|
-
});
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
```tsx
|
|
409
|
-
// ✅ 正确
|
|
410
|
-
interface UserInfo {
|
|
411
|
-
name: string;
|
|
412
|
-
age: number;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
export default defineWidget({
|
|
416
|
-
render() {
|
|
417
|
-
const viewData = getViewData<UserInfo>();
|
|
418
|
-
return <view>{viewData.name}</view>;
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
### 状态管理
|
|
424
|
-
|
|
425
|
-
#### ❌ 不在全局作用域定义状态
|
|
426
|
-
```tsx
|
|
427
|
-
// ❌ 错误 - 全局变量会在多个实例间共享
|
|
428
|
-
let count = 0;
|
|
429
|
-
|
|
430
|
-
export default defineWidget({
|
|
431
|
-
render() {
|
|
432
|
-
count++; // 所有实例共享这个 count
|
|
433
|
-
return <view>Count: {count}</view>;
|
|
434
|
-
}
|
|
435
|
-
});
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
```tsx
|
|
439
|
-
// ✅ 推荐 - 使用组件内状态,实例之间互不影响
|
|
440
|
-
import { useState } from '@doubao-apps/framework';
|
|
441
|
-
|
|
442
|
-
function CounterWidget() {
|
|
443
|
-
const [count, setCount] = useState(0);
|
|
444
|
-
|
|
445
|
-
return (
|
|
446
|
-
<view
|
|
447
|
-
onClick={() => {
|
|
448
|
-
setCount(prev => prev + 1);
|
|
449
|
-
}}
|
|
450
|
-
>
|
|
451
|
-
Count: {count}
|
|
452
|
-
</view>
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
export default defineWidget({
|
|
457
|
-
render() {
|
|
458
|
-
return <CounterWidget />;
|
|
459
|
-
}
|
|
460
|
-
});
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
## 📚 相关文档
|
|
464
|
-
|
|
465
|
-
- [组件开发指南](../guides/component-development.md)
|
|
466
|
-
- [最佳实践](../guides/best-practices.md)
|
|
467
|
-
- [性能优化](../guides/performance-optimization.md)
|