This commit is contained in:
Neo
2026-03-15 10:15:02 +08:00
parent 2dd217522c
commit 72bb11b34f
916 changed files with 65306 additions and 16102803 deletions

View File

@@ -0,0 +1,304 @@
# 开发最佳实践与常见坑
> 综合官方文档与社区经验
## setData 性能优化
setData 是小程序性能的关键瓶颈因为数据需要从逻辑层JS 线程)序列化后传输到视图层(渲染线程)。
### 原则
1. **减少数据量**:只传需要更新的字段
```javascript
// ❌ 错误:传整个列表
this.setData({ list: this.data.list })
// ✅ 正确:只更新变化的项
this.setData({ 'list[2].name': 'new name' })
```
2. **减少调用频率**:合并多次 setData
```javascript
// ❌ 错误:多次调用
this.setData({ a: 1 })
this.setData({ b: 2 })
this.setData({ c: 3 })
// ✅ 正确:合并为一次
this.setData({ a: 1, b: 2, c: 3 })
```
3. **后台页面不要 setData**
```javascript
// ❌ 错误:页面隐藏后仍在 setData如定时器
onShow() {
this._timer = setInterval(() => {
this.setData({ time: Date.now() })
}, 1000)
},
// ✅ 正确:页面隐藏时停止
onHide() {
clearInterval(this._timer)
}
```
4. **避免在 onPageScroll 中 setData**
```javascript
// ❌ 错误
onPageScroll(e) {
this.setData({ scrollTop: e.scrollTop })
}
// ✅ 正确:用 WXS 响应事件或节流
onPageScroll: throttle(function(e) {
if (this._needUpdate) {
this.setData({ isTop: e.scrollTop < 100 })
}
}, 100)
```
5. **大列表用纯数据字段**
```javascript
Component({
options: { pureDataPattern: /^_/ },
data: {
displayList: [], // 用于渲染
_rawList: [] // 纯数据,不传输到视图层
}
})
```
## 分包加载
### 基本分包
```json
// app.json
{
"pages": [
"pages/index/index",
"pages/logs/logs"
],
"subpackages": [
{
"root": "packageA",
"name": "pack-a",
"pages": [
"pages/cat/cat",
"pages/dog/dog"
]
},
{
"root": "packageB",
"name": "pack-b",
"pages": [
"pages/apple/apple"
]
}
]
}
```
**限制**
- 整个小程序所有分包大小不超过 20MB使用分包时
- 单个分包/主包大小不超过 2MB
- tabBar 页面必须在主包
### 独立分包
不依赖主包即可运行,适合独立功能页面(如活动页)。
```json
{
"subpackages": [
{
"root": "packageIndependent",
"pages": ["pages/activity/activity"],
"independent": true
}
]
}
```
**注意**独立分包中不能使用主包的公共资源js/组件/样式)。
### 分包预下载
```json
{
"preloadRule": {
"pages/index/index": {
"network": "all",
"packages": ["packageA"]
},
"pages/logs/logs": {
"network": "wifi",
"packages": ["packageB"]
}
}
}
```
## 小程序与 H5 的关键差异
| 特性 | H5 | 小程序 |
|------|-----|--------|
| DOM 操作 | 支持 document/window | ❌ 不支持 |
| BOM | 支持 | ❌ 不支持 |
| 路由 | URL hash/history | 页面栈(最多 10 层) |
| 样式 | 完整 CSS | WXSS部分 CSS 不支持) |
| 脚本 | 完整 JS + Web API | JS无 DOM API |
| 渲染 | 单线程 | 双线程(逻辑层 + 视图层) |
| 网络请求 | fetch/XMLHttpRequest | wx.request需配置域名 |
| 本地存储 | localStorage | wx.setStorage10MB |
| Cookie | 支持 | ❌ 不支持(需自行管理) |
| 动态创建元素 | 支持 | ❌ 不支持 |
| eval / new Function | 支持 | ❌ 不支持 |
| SVG | 支持 | 部分支持image src 可用) |
### 常见迁移坑
1. **没有 Cookie**:登录态需要自行通过 header 传递 token
2. **没有 DOM**:不能用 jQuery、不能 `document.getElementById`
3. **不支持动态执行代码**`eval()``new Function()` 都不可用
4. **样式差异**
- 不支持 `*` 通配符选择器
- 不支持 `>` `+` `~` 等关系选择器(部分版本已支持)
- 不支持 `@media` 的部分写法
- 不支持 `position: fixed` 在某些场景下的表现
5. **页面栈限制**:最多 10 层,超过后 navigateTo 会失败
6. **包大小限制**:主包 2MB总包 20MB
7. **网络请求域名白名单**:必须在管理后台配置
8. **不支持 npm 直接引入**:需要通过开发者工具构建 npm
## TypeScript 支持
小程序原生支持 TypeScript
```json
// tsconfig.json项目根目录
{
"compilerOptions": {
"strict": true,
"target": "ES2017",
"module": "ESNext",
"moduleResolution": "Node",
"lib": ["ES2017"],
"typeRoots": ["./typings"]
},
"include": ["**/*.ts"],
"exclude": ["node_modules"]
}
```
```typescript
// 页面 .ts 文件
Page({
data: {
msg: 'Hello' as string,
list: [] as Array<{ id: number; name: string }>
},
onLoad(options: Record<string, string | undefined>) {
const id = options.id
}
})
// 组件 .ts 文件
Component({
properties: {
title: { type: String, value: '' }
},
data: {
count: 0 as number
},
methods: {
increment() {
this.setData({ count: this.data.count + 1 })
}
}
})
```
## npm 支持
1. 在小程序根目录执行 `npm install`
2. 在开发者工具中:工具 → 构建 npm
3. 构建后会生成 `miniprogram_npm` 目录
4. 使用:`const dayjs = require('dayjs')`
**注意**
- 不是所有 npm 包都能在小程序中使用(不能依赖 Node.js 内置模块或浏览器 API
- 每次 `npm install` 后都需要重新构建 npm
## 自定义 tabBar
```json
// app.json
{
"tabBar": {
"custom": true,
"list": [
{ "pagePath": "pages/index/index", "text": "首页" },
{ "pagePath": "pages/mine/mine", "text": "我的" }
]
}
}
```
在根目录创建 `custom-tab-bar/` 组件:
```
custom-tab-bar/
├── index.js
├── index.json
├── index.wxml
└── index.wxss
```
## 骨架屏
开发者工具支持自动生成骨架屏:
1. 在模拟器中预览页面
2. 点击模拟器右下角「...」→「生成骨架屏」
3. 会自动生成 `页面名.skeleton.wxml``页面名.skeleton.wxss`
```json
// 页面 json 中引用
{
"initialRenderingCache": "static"
}
```
## 常见审核被拒原因
1. **功能不完整**:提交审核时确保所有功能可用
2. **测试账号未提供**:需要登录的小程序必须提供测试账号
3. **类目不符**:选择的服务类目与实际功能不匹配
4. **诱导分享/关注**:不能强制用户分享或关注公众号才能使用
5. **虚拟支付**iOS 不允许虚拟商品使用微信支付(需走 IAP
6. **内容违规**UGC 内容需要内容安全检测
7. **隐私协议**:需要配置隐私保护指引
8. **授权滥用**:不能在首页就弹出授权请求,需要在使用时才请求
## 调试技巧
```javascript
// 真机调试日志
const log = wx.getRealtimeLogManager()
log.info('info message')
log.warn('warn message')
log.error('error message')
// 性能监控
const performance = wx.getPerformance()
const observer = performance.createObserver((entryList) => {
console.log(entryList.getEntries())
})
observer.observe({ entryTypes: ['render', 'script', 'navigation'] })
```
## 在线查询
- 性能优化https://developers.weixin.qq.com/miniprogram/dev/framework/performance/tips.html
- 分包加载https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html
- npm 支持https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html
- 自定义 tabBarhttps://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html