3、项目结构设计:抖音小程序目录规范、全局配置(app.json)、页面配置(page.json)、组件注册机制
好,咱们进入第三讲。这一章我打算聊聊项目结构设计。说白了,就是你的代码该怎么摆,文件该怎么放。
很多新手开发者上来就写代码,写到后面发现目录乱成一锅粥。我自己刚做小程序那会儿也踩过这个坑——找文件要找半天,组件引用全靠猜路径。后来被坑了几次,才老老实实按规范来。
3.1 抖音小程序目录规范
抖音小程序的目录结构,其实和微信小程序很像。但有几个细节不一样,我重点说。
先看一个标准的项目目录长什么样:
my-miniapp/
├── app.json # 全局配置
├── app.js # 全局逻辑
├── app.ttss # 全局样式
├── project.config.json # 项目配置
├── pages/ # 页面目录
│ ├── index/
│ │ ├── index.js
│ │ ├── index.ttml
│ │ ├── index.ttss
│ │ └── index.json
│ └── detail/
│ ├── detail.js
│ ├── detail.ttml
│ ├── detail.ttss
│ └── detail.json
├── components/ # 公共组件
│ ├── header/
│ │ ├── header.js
│ │ ├── header.ttml
│ │ ├── header.ttss
│ │ └── header.json
│ └── footer/
│ ├── footer.js
│ ├── footer.ttml
│ ├── footer.ttss
│ └── footer.json
├── utils/ # 工具函数
│ ├── api.js
│ └── util.js
└── images/ # 静态资源
└── logo.png
核心要点:
- 每个页面一个文件夹,文件夹名就是页面名
- 页面文件必须包含 .js、.ttml、.ttss、.json 四个文件(.ttss 可以没有)
- 组件目录和页面目录结构一致,但放在 components/ 下
嗯,这里要注意:抖音小程序的模板文件后缀是 .ttml,样式文件后缀是 .ttss。这和微信的 .wxml、.wxss 不一样。我第一次迁移项目时,就因为后缀名没改,编译报错了半天。
3.2 全局配置 app.json
app.json 是整个小程序的配置文件。它决定了你的小程序长什么样、有哪些页面、用什么窗口样式。
我直接给一个生产环境的配置示例:
{
"pages": [
"pages/index/index",
"pages/detail/detail",
"pages/user/user"
],
"window": {
"navigationBarTitleText": "我的小程序",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"backgroundColor": "#f5f5f5",
"backgroundTextStyle": "dark"
},
"tabBar": {
"color": "#999999",
"selectedColor": "#ff5500",
"backgroundColor": "#ffffff",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "images/home.png",
"selectedIconPath": "images/home_active.png"
},
{
"pagePath": "pages/user/user",
"text": "我的",
"iconPath": "images/user.png",
"selectedIconPath": "images/user_active.png"
}
]
},
"networkTimeout": {
"request": 10000,
"connectSocket": 5000,
"uploadFile": 30000
},
"debug": false
}
避坑指南:
我曾经在配置 tabBar 时,把 pagePath 写成了绝对路径(比如 /pages/index/index),结果 tab 死活不显示。后来才发现,这里必须用相对路径,不能加斜杠开头。
几个关键配置项,我挑重点说:
| 配置项 | 说明 | 我的建议 |
|---|---|---|
| pages | 页面路径列表,第一项是首页 | 按业务模块分组排列,方便维护 |
| window | 全局窗口样式 | 导航栏颜色统一用品牌色 |
| tabBar | 底部导航栏 | 最多5个tab,图标用纯色SVG |
| networkTimeout | 网络超时时间 | 请求超时建议10秒以上 |
| debug | 调试模式开关 | 上线前务必设为 false |
注意:
pages 数组的顺序很重要。第一项就是小程序的首页。如果你改了顺序,首页也会变。我有个同事就因为这个,把用户引导页和首页搞反了,上线后用户直接看到了引导页...嗯,那场面挺尴尬的。
3.3 页面配置 page.json
每个页面都可以有自己的 .json 配置文件。它会覆盖 app.json 中的全局配置。
举个例子,你的首页可能不需要导航栏,但详情页需要:
// pages/index/index.json
{
"navigationBarTitleText": "首页",
"navigationStyle": "custom", // 自定义导航栏
"enablePullDownRefresh": true,
"backgroundColor": "#f8f8f8"
}
// pages/detail/detail.json
{
"navigationBarTitleText": "商品详情",
"navigationBarBackgroundColor": "#ff5500",
"navigationBarTextStyle": "white",
"enablePullDownRefresh": false
}
我个人习惯把页面级别的配置都写在 page.json 里,而不是全局配置。为什么?因为每个页面的需求不一样。比如首页需要下拉刷新,但详情页不需要。你想想看,如果都写在全局配置里,那所有页面都得跟着改,多麻烦。
3.4 组件注册机制
抖音小程序的组件注册,分两种:全局注册和局部注册。
3.4.1 全局注册
在 app.json 中注册,所有页面都能用:
{
"usingComponents": {
"my-header": "/components/header/header",
"my-footer": "/components/footer/footer"
}
}
3.4.2 局部注册
在页面的 .json 中注册,只有当前页面能用:
// pages/index/index.json
{
"usingComponents": {
"custom-card": "/components/card/card"
}
}
我的经验:
全局注册虽然方便,但会增加包体积。我建议只把那些真正通用的组件(比如导航栏、底部栏)注册到全局。业务组件尽量局部注册,按需加载。
组件本身的结构和页面一样,但多了一个 Component 构造器:
// components/header/header.js
Component({
properties: {
title: {
type: String,
value: '默认标题'
},
showBack: {
type: Boolean,
value: false
}
},
data: {
// 内部数据
},
methods: {
onBack() {
this.triggerEvent('back')
}
}
})
组件模板里用 properties 接收外部传值:
<!-- components/header/header.ttml -->
<view class="header">
<view class="back" tt:if="{{showBack}}" bindtap="onBack">
<text>返回</text>
</view>
<text class="title">{{title}}</text>
</view>
在页面中使用组件:
<!-- pages/index/index.ttml -->
<my-header title="首页" showBack="{{false}}" bind:back="onHeaderBack" />
避坑指南:
我曾经在组件里用 this.data 直接修改数据,结果视图没更新。后来才想起来,组件里也要用 this.setData() 才行。嗯,这个坑我印象特别深,因为当时排查了整整一个下午。
3.5 总结一下
这一章的内容其实不难,但很重要。目录规范决定了你的项目好不好维护,配置项决定了你的小程序长什么样,组件注册机制决定了代码能不能复用。
我个人建议,在项目一开始就把目录结构搭好,配置项写清楚。别等到代码写了一半再来重构,那滋味可不好受。
下一章我会讲页面生命周期和数据通信,到时候咱们再聊。