专注小程序 / APP 开发,用代码改变生活

获取方案
全国分站 主站首页 北京分站 石家庄分站 唐山分站 保定分站 廊坊分站 沧州分站 郑州分站 邯郸分站

小程序开发架构:从分层到落地

小程序开发 2026-11-07 3 阅读 0 点赞 原创

小程序看起来轻量,但一旦业务变复杂,页面数量、接口调用、状态共享会迅速膨胀。如果没有清晰的架构约束,代码会在两三个月内变成一团难以维护的泥。这篇文章从分层、状态、通信、构建四个角度,讲一套可以直接落地的小程序开发架构。

小程序开发架构:从分层到落地

一、先分层,再谈其他

小程序官方没有强制架构,但推荐的最小分层是三层:页面层、逻辑层、数据层。我的做法是在 src 下按职责划分目录,而不是按页面类型平铺。

src/
  pages/          # 页面,只做渲染与事件转发
  components/     # 通用组件
  services/       # 业务逻辑,纯函数优先
  api/            # 接口定义与请求封装
  store/          # 全局状态
  utils/          # 工具函数
  config/         # 环境配置

关键约束只有一条:页面层不允许直接调用 wx.request。所有数据获取都走 api 层,业务组装走 services 层。这样页面代码只剩下 setData 和事件绑定,测试与复用都变得简单。

二、请求层要做的事比想象中多

很多项目的 api 层只是把 URL 拼一拼,结果登录态、错误提示、loading 状态散落在各个页面。建议把请求封装成一个带拦截能力的实例:

// api/request.js
const BASE_URL = process.env.API_BASE

function request(options) {
  return new Promise((resolve, reject) => {
    wx.request({
      url: BASE_URL + options.url,
      method: options.method || 'GET',
      data: options.data || {},
      header: {
        'content-type': 'application/json',
        Authorization: wx.getStorageSync('token') || ''
      },
      success(res) {
        if (res.statusCode === 401) {
          // 统一跳登录,避免每个页面重复判断
          wx.navigateTo({ url: '/pages/login/index' })
          return reject(new Error('UNAUTHORIZED'))
        }
        if (res.data.code !== 0) {
          wx.showToast({ title: res.data.msg, icon: 'none' })
          return reject(res.data)
        }
        resolve(res.data.data)
      },
      fail: reject
    })
  })
}

这一层解决三件事:统一鉴权、统一错误提示、统一返回值结构。页面里只需要 const list = await api.getList(),不必关心 token 和错误码。

三、状态管理别急着上库

小程序的全局状态其实很少:用户信息、登录态、少量配置。完全可以用一个极简的发布订阅实现,没必要引入重量级方案。

// store/index.js
const state = { userInfo: null, token: '' }
const listeners = new Set()

export function setState(patch) {
  Object.assign(state, patch)
  listeners.forEach(fn => fn(state))
}

export function subscribe(fn) {
  listeners.add(fn)
  return () => listeners.delete(fn)
}

export function getState() {
  return state
}

页面在 onLoad 中订阅,在 onUnload 中取消订阅。注意一定要取消,否则页面销毁后回调仍在执行,会触发对已卸载页面的 setData,控制台出现警告甚至内存泄漏。

四、组件通信的边界

父子组件用 properties 与 triggerEvent 就够了。真正容易出问题的是跨层级通信,比如弹窗、登录框这类全局组件。推荐两种方式:

  • 简单场景:用上面的事件总线,全局组件订阅特定事件;
  • 复杂场景:把全局组件挂在根页面,通过 selectComponent 获取实例调用方法。

无论哪种,都要明确“谁拥有状态”。我的习惯是:全局组件自己管理显隐,业务方只发指令,避免多处同时修改同一个布尔值导致状态错乱。

五、构建与分包

主包体积是硬约束。架构上要提前规划分包:把低频页面(活动页、设置页、帮助中心)放进分包,公共组件和工具放主包。配置示例:

{
  "pages": ["pages/index/index"],
  "subPackages": [
    {
      "root": "packageActivity",
      "pages": ["pages/detail/index"]
    }
  ],
  "preloadRule": {
    "pages/index/index": {
      "network": "all",
      "packages": ["packageActivity"]
    }
  }
}

配合 preloadRule 在首页空闲时预下载分包,用户点进去几乎无感。这一步对留存的影响比很多 UI 优化都大。

六、性能上的几个硬指标

  • setData 单次数据量控制在几十 KB 以内,列表分页加载,不要一次性塞几百条;
  • 长列表使用 recycle-view 或手动虚拟列表,避免节点数爆炸;
  • 图片走 CDN 并带尺寸参数,首屏图片开启 lazy-load;
  • 避免在 onPageScroll 里频繁 setData,用节流或改由 CSS 实现动效。

如果项目用云开发,数据库查询同样要注意索引和分页,limit 默认 20 条,聚合查询的 lookup 在数据量大时开销明显,能冗余字段就不要频繁联表。

七、写在最后

架构不是越复杂越好,而是让“新增一个页面”这件事有固定路径可走。分层清晰、请求统一、状态可控、分包合理,这四点做到,小程序的维护成本会下降一个量级。真正的架构决策,往往发生在项目第二个月而不是第一天,所以留好扩展点比一次设计到位更重要。

小程序开发步骤全流程拆解小程序组件开发实战指南

评论 (0)

还没有评论,快来抢沙发吧~

好想法,值得被认真交付

从小程序、APP 到全栈网站,一站式把想法变成可落地的产品

微信咨询

微信扫码,直接沟通需求