3、项目结构:目录规范、页面路由配置、全局样式与局部样式、组件化思维

好,咱们进入第三章。这一章我打算聊聊项目结构。说实话,我见过太多小程序项目,刚开始随便搭,等做到一半,目录乱得像一锅粥。找文件靠猜,改样式靠翻,组件复用全靠复制粘贴——这哪行?

今天我就把我在多个跨端项目里沉淀下来的那套「骨架」分享给你。你跟着搭一遍,后面写代码会舒服很多。

3.1 目录规范:别让文件「流浪」

先说说目录。我个人习惯把项目分成三层:入口层、业务层、公共层。说白了,就是「启动入口」放最外面,「页面模块」放中间,「通用能力」放里面。

给你看一个我常用的结构:

miniprogram/
├── app.js              # 全局入口
├── app.json            # 全局配置(路由、窗口等)
├── app.wxss            # 全局样式
├── project.config.json # 项目配置
│
├── pages/              # 业务页面
│   ├── index/
│   │   ├── index.js
│   │   ├── index.wxml
│   │   ├── index.wxss
│   │   └── index.json
│   ├── detail/
│   │   └── ...
│   └── user/
│       └── ...
│
├── components/         # 公共组件
│   ├── nav-bar/
│   ├── loading/
│   └── empty-state/
│
├── utils/              # 工具函数
│   ├── request.js
│   ├── format.js
│   └── storage.js
│
├── assets/             # 静态资源
│   ├── images/
│   └── icons/
│
└── styles/             # 公共样式
    ├── variables.wxss
    └── mixins.wxss

嗯,这里要注意:每个页面文件夹里只放它自己的文件。我在项目中遇到过有人把公共组件塞到页面目录里,结果其他页面想用还得跨目录引用,改起来特别痛苦。

核心原则:「页面私有」放 pages 里,「跨页面复用」放 components 里,「全局能力」放根目录。

3.2 页面路由配置:别让用户迷路

路由配置在 app.jsonpages 字段里。你想想看,这就像给房子装门牌号——顺序很重要。

{
  "pages": [
    "pages/index/index",
    "pages/detail/detail",
    "pages/user/user"
  ]
}

为什么顺序重要?因为数组第一项就是首页。我建议你把最常访问的页面放前面,这样小程序启动时预加载更快。

另外,跨端开发时要注意:微信小程序最多支持 200 个页面,但支付宝、百度小程序可能限制不同。我曾经在做一个电商项目时,页面数飙到 180 多个,差点踩到上限。后来我把一些低频页面改成了 webview 承载,才松了口气。

避坑指南:路由跳转时,路径不要写死。我习惯在 utils/router.js 里维护一个路由映射表,这样改路径时只改一处就行。

3.3 全局样式与局部样式:别让样式「打架」

全局样式写在 app.wxss 里,局部样式写在页面的 .wxss 里。这俩的关系,说白了就是「公共规则」和「特例规则」。

我一般会在全局样式里放这些:

  • CSS 变量:比如主色、字号、间距
  • 重置样式:清除默认边距、盒模型统一
  • 通用类:比如 .flex-center.text-ellipsis

举个例子:

/* app.wxss */
page {
  --primary-color: #07c160;
  --font-size-base: 28rpx;
  box-sizing: border-box;
}

.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

局部样式就只管当前页面的特殊需求。比如首页的 banner 要圆角,详情页的标题要加粗——这些写在页面自己的 .wxss 里就行。

我的小技巧:@import 引入公共样式变量文件,这样每个页面都能用上统一的颜色和字号,改起来也方便。

3.4 组件化思维:像搭积木一样写代码

组件化,说白了就是把重复的 UI 和逻辑抽出来,封装成一个独立的「零件」。你想想看,一个按钮、一个加载动画、一个空状态提示——这些在多个页面里都会出现,难道每次都重写一遍?

我建议你从这三个维度来思考组件化:

  1. UI 组件:纯展示,比如按钮、卡片、图标
  2. 功能组件:带交互逻辑,比如下拉刷新、弹窗、表单
  3. 业务组件:跟具体业务绑定,比如商品卡片、订单列表

来看一个简单的组件示例:

<!-- components/loading/loading.wxml -->
<view class="loading-container">
  <view class="loading-spinner"></view>
  <text class="loading-text">{{ text }}</text>
</view>
/* components/loading/loading.wxss */
.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 40rpx 0;
}

.loading-spinner {
  width: 60rpx;
  height: 60rpx;
  border: 4rpx solid #e0e0e0;
  border-top-color: var(--primary-color);
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
// components/loading/loading.js
Component({
  properties: {
    text: {
      type: String,
      value: '加载中...'
    }
  }
})

然后在页面里引用:

<!-- pages/index/index.wxml -->
<loading text="正在加载数据" />

组件化的好处:改一处,所有地方都生效。我在项目中遇到过改一个按钮样式,结果要翻 20 多个页面去改——从那以后,我再也不写重复的 UI 代码了。

3.5 跨端兼容:目录与组件的「方言」处理

不同平台的目录结构大同小异,但有几个细节要注意:

平台 入口文件 组件后缀 特殊目录
微信 app.js .wxml / .wxss
支付宝 app.js .axml / .acss
百度 app.js .swan / .css
字节跳动 app.js .ttml / .ttss

你看,结构几乎一样,就是文件后缀不同。所以我的做法是:用一套目录结构,通过构建工具自动转换后缀。比如用 Gulp 或 Webpack 插件,把 .wxml 转成 .axml.swan 等。

注意:组件引用路径要保持一致。不同平台对路径大小写敏感程度不同,我建议全部用小写,避免在 Linux 构建环境下报错。

3.6 实战建议:从零搭一个跨端项目骨架

好,理论说完了,咱们动手。我建议你按这个步骤来:

  1. 初始化项目:用官方脚手架创建基础模板
  2. 整理目录:按上面说的三层结构重新组织
  3. 配置路由:在 app.json 里按访问频率排序
  4. 定义全局样式:写 CSS 变量和通用类
  5. 抽取第一个组件:比如 loadingnav-bar
  6. 测试跨端:分别在微信、支付宝开发者工具里跑一遍

我记得第一次带团队做跨端项目时,光目录结构就改了三次。后来发现,越早定好规范,后面越省心。你花半小时搭好骨架,后面能省下几十个小时的改 bug 时间。

最后一个小建议:把目录规范和组件命名规则写进项目的 README 里,新同事来了直接看,不用你一个个去讲。

下一章,咱们聊聊数据管理与状态同步——这可是跨端开发里最容易踩坑的地方。