AI编程—微信小程序开发规范

微信小程序开发规范

本文档为微信小程序项目的统一开发规范,适用于人工开发与 AI 辅助开发场景。所有代码必须遵循本规范,以保证项目的可维护性、可扩展性和一致性。


目录

  • [1. 代码结构规范](#1. 代码结构规范)
  • [2. 分包规范](#2. 分包规范)
  • [3. 页面跳转规范](#3. 页面跳转规范)
  • [4. 组件封装规范](#4. 组件封装规范)
  • [5. 静态资源处理规范](#5. 静态资源处理规范)
  • [6. API 与网络请求规范](#6. API 与网络请求规范)
  • [7. 状态管理规范](#7. 状态管理规范)
  • [8. 样式规范](#8. 样式规范)
  • [9. 性能优化规范](#9. 性能优化规范)
  • [10. 安全规范](#10. 安全规范)

1. 代码结构规范

1.1 整体目录结构

复制代码
miniprogram/
├── app.js                  # 小程序入口
├── app.json                # 全局配置
├── app.wxss                # 全局样式
├── sitemap.json            # 站点地图配置
├── project.config.json     # 项目配置
├── envList.js              # 环境变量配置
│
├── pages/                  # 主包页面(TabBar 页面 + 核心页面)
│   ├── index/              # 首页
│   │   ├── index.js
│   │   ├── index.json
│   │   ├── index.wxml
│   │   └── index.wxss
│   └── ...
│
├── packageA/               # 分包 A(按业务模块划分)
│   └── pages/
│       └── ...
│
├── components/             # 全局公共组件
│   ├── base/               # 基础组件(按钮、输入框等)
│   ├── business/           # 业务组件(商品卡片、订单列表等)
│   └── layout/             # 布局组件(导航栏、底部栏等)
│
├── utils/                  # 工具函数
│   ├── request.js          # 网络请求封装
│   ├── storage.js          # 本地存储封装
│   ├── format.js           # 格式化工具
│   ├── validate.js         # 校验工具
│   └── auth.js             # 鉴权工具
│
├── api/                    # 接口定义层
│   ├── modules/            # 按业务模块拆分
│   │   ├── user.js
│   │   ├── order.js
│   │   └── ...
│   └── index.js            # 统一导出
│
├── store/                  # 状态管理(如使用 MobX / 自实现)
│   ├── index.js
│   └── modules/
│
├── styles/                 # 全局样式变量与混入
│   ├── variables.wxss      # 样式变量
│   ├── mixin.wxss          # 样式混入
│   └── reset.wxss          # 样式重置
│
├── assets/                 # 静态资源
│   ├── images/             # 图片资源
│   ├── icons/              # 图标资源
│   └── fonts/              # 字体资源
│
├── config/                 # 配置文件
│   ├── routes.js           # 路由配置表
│   └── constants.js        # 常量定义
│
└── behaviors/              # 公共行为(代码复用)
    └── ...

1.2 文件命名规范

类型 命名规则 示例
页面目录 小写 + 中划线(kebab-case) order-detail/
页面文件 与目录同名 order-detail.js
组件目录 小写 + 中划线 goods-card/
组件文件 与目录同名 goods-card.js
工具函数 小驼峰(camelCase) formatDate.js
常量文件 全大写 + 下划线 USER_STATUS.js
图片资源 小写 + 下划线 icon_home.png

1.3 JS 代码规范

1.3.1 基本规则
  • 统一使用 ES6+ 语法,优先使用 const / let,禁止使用 var
  • 字符串统一使用 单引号,模板字符串使用反引号
  • 缩进使用 2 个空格
  • 语句末尾 不加分号(与现代前端风格保持一致)
  • 单行代码长度不超过 120 字符
1.3.2 页面/组件 JS 结构顺序
javascript 复制代码
// 1. 引入依赖(按顺序:第三方 → 工具 → 组件 → 样式)
import { formatDate } from '../../utils/format'
import { getUserInfo } from '../../api/modules/user'

// 2. 常量定义
const PAGE_SIZE = 20

// 3. Page / Component 定义
Page({
  // 3.1 数据
  data: {
    list: [],
    loading: false,
    hasMore: true
  },

  // 3.2 生命周期(按执行顺序排列)
  onLoad(options) {
    this.initData(options)
  },

  onShow() {},

  onReady() {},

  onHide() {},

  onUnload() {},

  onPullDownRefresh() {},

  onReachBottom() {},

  onShareAppMessage() {},

  // 3.3 自定义方法(按功能分组,私有方法以下划线开头)
  // --- 数据初始化 ---
  async initData(options) {
    // ...
  },

  // --- 网络请求 ---
  async fetchList() {
    // ...
  },

  // --- 事件处理 ---
  handleItemTap(e) {
    // ...
  },

  // --- 私有方法 ---
  _calcTotal() {
    // ...
  }
})
1.3.3 函数规范
  • 函数名使用 小驼峰 ,动词开头:getUserInfohandleTapcalcPrice
  • 事件处理函数统一以 handle 开头:handleSubmithandleDelete
  • 异步函数统一使用 async/await,配合 try/catch 错误处理
  • 函数参数超过 3 个时,使用对象传参
javascript 复制代码
// ✅ 推荐
function createOrder({ goodsId, count, addressId, couponId }) {
  // ...
}

// ❌ 不推荐
function createOrder(goodsId, count, addressId, couponId) {
  // ...
}

1.4 WXML 规范

  • 标签名一律小写,属性值使用双引号
  • 布尔值属性省略值:<button loading /> 而非 <button loading="{``{true}}" />
  • 复杂逻辑抽取到 JS 的 computedwxs 中,WXML 只做展示
  • wx:for 必须指定 wx:key,列表项有唯一 id 时用 id,否则用 *this
xml 复制代码
<!-- ✅ 推荐 -->
<view class="goods-list">
  <view
    wx:for="{{list}}"
    wx:key="id"
    class="goods-item"
    bindtap="handleItemTap"
    data-id="{{item.id}}"
  >
    <image class="goods-img" src="{{item.cover}}" mode="aspectFill" />
    <text class="goods-name">{{item.name}}</text>
  </view>
</view>

1.5 JSON 配置规范

  • 页面级 json 只配置当前页面独有的属性,公共配置放 app.json
  • 组件 json 必须设置 "component": true
  • 按需引入组件,避免全局注册过多组件

2. 分包规范

2.1 分包原则

原则 说明
主包精简 主包只放 TabBar 页面和核心公共资源,体积控制在 2MB 以内
按业务划分 每个分包对应一个独立业务模块,模块间低耦合
按需加载 非首屏页面全部放入分包,减少主包体积
公共抽离 多分包共用的组件/工具抽到主包或独立公共分包

2.2 分包划分策略

复制代码
主包(main)
├── TabBar 页面(首页、分类、购物车、我的)
├── 全局公共组件
├── 工具函数
├── 全局样式
└── 基础配置

分包 A:商品模块(package-goods)
├── 商品详情
├── 商品搜索
├── 商品分类列表
└── 商品评价

分包 B:订单模块(package-order)
├── 订单列表
├── 订单详情
├── 确认订单
├── 售后申请
└── 退款进度

分包 C:用户模块(package-user)
├── 个人资料
├── 地址管理
├── 收藏夹
├── 优惠券
└── 积分中心

分包 D:营销模块(package-marketing)
├── 拼团活动
├── 秒杀活动
├── 签到
└── 邀请好友

独立分包:登录模块(package-login)
├── 登录页
├── 授权页
└── 绑定手机号

2.3 分包配置示例

json 复制代码
// app.json
{
  "pages": [
    "pages/index/index",
    "pages/category/category",
    "pages/cart/cart",
    "pages/user/user"
  ],
  "subpackages": [
    {
      "root": "package-goods",
      "name": "goods",
      "pages": [
        "pages/detail/detail",
        "pages/search/search",
        "pages/list/list"
      ]
    },
    {
      "root": "package-order",
      "name": "order",
      "pages": [
        "pages/list/list",
        "pages/detail/detail",
        "pages/confirm/confirm"
      ]
    }
  ],
  "preloadRule": {
    "pages/index/index": {
      "network": "wifi",
      "packages": ["goods"]
    },
    "pages/category/category": {
      "network": "all",
      "packages": ["goods"]
    }
  },
  "lazyCodeLoading": "requiredComponents"
}

2.4 分包注意事项

  1. TabBar 页面必须在主包,不能放入分包
  2. 分包之间不能互相引用 JS 文件和组件,公共资源放主包
  3. 主包不能引用分包的资源,分包可以引用主包资源
  4. 图片等静态资源尽量放入 CDN,减少包体积
  5. 使用 分包预下载 优化用户体验,在进入相关页面前预加载分包
  6. 启用 lazyCodeLoading: "requiredComponents" 按需注入代码

3. 页面跳转规范

3.1 路由统一管理

所有页面路径必须在路由配置表中统一定义,禁止硬编码路径。

javascript 复制代码
// config/routes.js

/**
 * 路由配置表
 * path: 页面路径(绝对路径)
 * name: 路由名称(唯一标识)
 * package: 所属分包(主包为空)
 * needAuth: 是否需要登录
 */
const ROUTES = {
  // 主包
  HOME: { path: '/pages/index/index', name: 'home', needAuth: false },
  CATEGORY: { path: '/pages/category/category', name: 'category', needAuth: false },
  CART: { path: '/pages/cart/cart', name: 'cart', needAuth: false },
  USER: { path: '/pages/user/user', name: 'user', needAuth: false },

  // 商品分包
  GOODS_DETAIL: { path: '/package-goods/pages/detail/detail', name: 'goodsDetail', package: 'goods', needAuth: false },
  GOODS_SEARCH: { path: '/package-goods/pages/search/search', name: 'goodsSearch', package: 'goods', needAuth: false },

  // 订单分包
  ORDER_LIST: { path: '/package-order/pages/list/list', name: 'orderList', package: 'order', needAuth: true },
  ORDER_DETAIL: { path: '/package-order/pages/detail/detail', name: 'orderDetail', package: 'order', needAuth: true },
  ORDER_CONFIRM: { path: '/package-order/pages/confirm/confirm', name: 'orderConfirm', package: 'order', needAuth: true }
}

export default ROUTES

3.2 跳转方式选择

场景 API 说明
普通页面跳转(非 TabBar) wx.navigateTo 保留当前页,最多 10 层
关闭当前页跳转 wx.redirectTo 替换当前页,不保留
跳转到 TabBar 页面 wx.switchTab 只能用于 TabBar 页面
关闭所有页跳转 wx.reLaunch 清空页面栈,重新开始
返回上一页 wx.navigateBack 返回页面栈中的页面

3.3 统一跳转封装

javascript 复制代码
// utils/navigator.js
import ROUTES from '../config/routes'
import { checkAuth } from './auth'

/**
 * 统一页面跳转方法
 * @param {string} routeName - 路由名称(ROUTES 中的 key)
 * @param {object} params - 页面参数
 * @param {object} options - 跳转选项
 * @param {string} options.type - 跳转类型:navigateTo / redirectTo / switchTab / reLaunch
 * @param {boolean} options.skipAuth - 是否跳过鉴权检查
 */
function navigateTo(routeName, params = {}, options = {}) {
  const route = ROUTES[routeName]
  if (!route) {
    console.error(`[navigator] 路由不存在: ${routeName}`)
    return
  }

  // 鉴权检查
  if (route.needAuth && !options.skipAuth) {
    const isLogin = checkAuth()
    if (!isLogin) {
      // 未登录,跳转到登录页
      wx.navigateTo({
        url: `${ROUTES.LOGIN.path}?redirect=${encodeURIComponent(routeName)}`
      })
      return
    }
  }

  // 拼接参数
  let url = route.path
  const queryStr = Object.keys(params)
    .filter(key => params[key] !== undefined && params[key] !== null)
    .map(key => `${key}=${encodeURIComponent(params[key])}`)
    .join('&')

  if (queryStr) {
    url += `?${queryStr}`
  }

  // 选择跳转方式
  const type = options.type || 'navigateTo'

  // TabBar 页面强制使用 switchTab
  if (isTabBarPage(routeName)) {
    return wx.switchTab({ url })
  }

  switch (type) {
    case 'redirectTo':
      return wx.redirectTo({ url })
    case 'reLaunch':
      return wx.reLaunch({ url })
    case 'switchTab':
      return wx.switchTab({ url })
    default:
      return wx.navigateTo({ url })
  }
}

/**
 * 返回上一页
 * @param {number} delta - 返回层数
 */
function navigateBack(delta = 1) {
  const pages = getCurrentPages()
  if (pages.length <= delta) {
    // 无法返回时,回到首页
    return wx.switchTab({ url: ROUTES.HOME.path })
  }
  return wx.navigateBack({ delta })
}

// 判断是否为 TabBar 页面
function isTabBarPage(routeName) {
  const tabBarRoutes = ['HOME', 'CATEGORY', 'CART', 'USER']
  return tabBarRoutes.includes(routeName)
}

export default {
  to: navigateTo,
  back: navigateBack
}

3.4 使用示例

javascript 复制代码
import navigator from '../../utils/navigator'

// 普通跳转
navigator.to('GOODS_DETAIL', { id: 123 })

// 带参数跳转
navigator.to('ORDER_LIST', { status: 'pending' })

// 重定向(不保留当前页)
navigator.to('LOGIN', {}, { type: 'redirectTo' })

// 返回上一页
navigator.back()

// 返回两层
navigator.back(2)

3.5 参数传递规范

  • 简单参数:通过 URL query 传递(字符串、数字)
  • 复杂对象 :使用 storage 临时存储 + 页面 id 关联,或使用全局状态管理
  • 禁止在 URL 中传递超长字符串(> 200 字符),避免 URL 截断
  • 接收参数时必须做默认值处理
javascript 复制代码
onLoad(options) {
  const id = Number(options.id) || 0
  const type = options.type || 'default'
  // ...
}

4. 组件封装规范

4.1 组件分类

分类 目录 说明 示例
基础组件 components/base/ 通用 UI 组件,无业务逻辑 base-buttonbase-input
业务组件 components/business/ 包含业务逻辑的可复用组件 goods-cardorder-item
布局组件 components/layout/ 页面布局相关 nav-barbottom-bar
页面级组件 pages/xxx/components/ 仅当前页面使用的组件 就近放置

4.2 组件设计原则

  1. 单一职责:一个组件只做一件事,功能明确
  2. 可配置 :通过 properties 配置,不硬编码业务数据
  3. 受控组件:组件状态由父组件控制,内部不维护核心数据
  4. 事件冒泡:自定义事件命名规范,语义清晰
  5. 插槽灵活 :合理使用 slot 支持内容定制

4.3 组件文件结构

复制代码
components/
└── base/
    └── base-button/
        ├── index.js        # 组件逻辑
        ├── index.json      # 组件配置
        ├── index.wxml      # 组件模板
        ├── index.wxss      # 组件样式
        └── README.md       # 组件文档(可选,复杂组件必备)

4.4 组件 JS 规范

javascript 复制代码
// components/base/base-button/index.js
Component({
  // 启用多 slot 支持
  options: {
    multipleSlots: true,
    // 样式隔离:apply-shared 允许继承外部样式
    styleIsolation: 'apply-shared'
  },

  // 组件属性
  properties: {
    // 按钮类型:primary / default / danger
    type: {
      type: String,
      value: 'default'
    },
    // 按钮尺寸:large / medium / small
    size: {
      type: String,
      value: 'medium'
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      value: false
    },
    // 是否加载中
    loading: {
      type: Boolean,
      value: false
    },
    // 自定义样式类
    customClass: {
      type: String,
      value: ''
    }
  },

  // 组件内部数据
  data: {
    innerLoading: false
  },

  // 监听属性变化
  observers: {
    'loading': function(val) {
      this.setData({ innerLoading: val })
    }
  },

  // 组件方法
  methods: {
    handleTap(e) {
      if (this.data.disabled || this.data.innerLoading) return

      // 触发父组件事件
      this.triggerEvent('tap', {
        // 可携带额外数据
        timestamp: Date.now()
      }, {
        bubbles: false,
        composed: false
      })
    }
  },

  // 生命周期
  lifetimes: {
    attached() {
      // 组件实例进入页面节点树
    },
    detached() {
      // 组件实例被移除
    }
  },

  // 所在页面生命周期
  pageLifetimes: {
    show() {},
    hide() {},
    resize() {}
  }
})

4.5 组件通信规范

4.5.1 父 → 子:properties 传参
xml 复制代码
<!-- 父组件 -->
<goods-card
  goods="{{item}}"
  show-price="{{true}}"
  bind:add-cart="handleAddCart"
/>
javascript 复制代码
// 子组件
properties: {
  goods: {
    type: Object,
    value: {}
  },
  showPrice: {
    type: Boolean,
    value: true
  }
}
4.5.2 子 → 父:triggerEvent 事件
javascript 复制代码
// 子组件
this.triggerEvent('change', { value: newValue })

// 父组件
handleChange(e) {
  console.log(e.detail.value)
}
4.5.3 父调用子方法:selectComponent
javascript 复制代码
// 父组件
const dialog = this.selectComponent('#dialog')
dialog.show()
4.5.4 兄弟组件通信

通过父组件中转,或使用全局状态管理,禁止直接互相调用。

4.6 组件使用规范

  • 在页面 json 中按需引入,禁止全局注册所有组件
  • 组件名使用中划线命名:<goods-card />
  • 多个属性换行排列,提升可读性
  • 自定义事件统一使用 bind: 前缀:bind:change="handleChange"

5. 静态资源处理规范

5.1 资源分类与目录

复制代码
assets/
├── images/              # 图片资源
│   ├── common/          # 通用图片
│   ├── tabbar/          # TabBar 图标
│   ├── empty/           # 空状态图
│   └── banner/          # Banner 图
├── icons/               # 图标(建议用 iconfont 或 SVG)
└── fonts/               # 字体文件

5.2 图片规范

5.2.1 格式选择
场景 推荐格式 说明
照片类图片 JPG / WebP 体积小,适合商品图、Banner
图标、Logo PNG(透明) 支持透明背景
简单图形 SVG 矢量图,缩放不失真
动画 GIF / Lottie 动效图标用 Lottie
5.2.2 尺寸规范
  • 图标:@2x / @3x 两套,基础尺寸 24px / 32px / 48px
  • 商品主图:建议 750px × 750px(正方形)
  • Banner 图:建议 750px × 400px(宽高比约 1.875:1)
  • 所有图片上线前必须压缩,单张图片不超过 200KB
5.2.3 命名规范
复制代码
{类型}_{模块}_{描述}_{状态}.{扩展名}

示例:
icon_home_normal.png      # 首页图标-正常态
icon_home_active.png      # 首页图标-选中态
img_goods_default.png     # 商品默认图
img_empty_cart.png        # 购物车空状态图
bg_login.jpg              # 登录页背景图

5.3 图标方案

优先使用 Iconfont(字体图标),原因:

  • 体积小,支持任意缩放
  • 可通过 color 属性改变颜色
  • 支持多色图标
css 复制代码
/* styles/iconfont.wxss */
@font-face {
  font-family: 'iconfont';
  src: url('https://at.alicdn.com/t/xxx.woff2') format('woff2');
}

.iconfont {
  font-family: 'iconfont' !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
}

使用方式:

xml 复制代码
<text class="iconfont">&#xe600;</text>

5.4 CDN 管理

所有静态资源必须上传 CDN,禁止打包进小程序代码包:

javascript 复制代码
// config/constants.js
export const CDN_BASE = 'https://cdn.example.com/miniprogram'

export const ASSETS = {
  // 图片
  IMG_GOODS_DEFAULT: `${CDN_BASE}/images/common/img_goods_default.png`,
  IMG_EMPTY_CART: `${CDN_BASE}/images/empty/img_empty_cart.png`,

  // TabBar 图标
  ICON_HOME_NORMAL: `${CDN_BASE}/images/tabbar/icon_home_normal.png`,
  ICON_HOME_ACTIVE: `${CDN_BASE}/images/tabbar/icon_home_active.png`
}

页面中使用:

javascript 复制代码
import { ASSETS } from '../../config/constants'

Page({
  data: {
    defaultImg: ASSETS.IMG_GOODS_DEFAULT
  }
})
xml 复制代码
<image src="{{defaultImg}}" mode="aspectFill" />

5.5 图片懒加载

  • 列表中的图片统一开启 lazy-load 属性
  • 使用 image 组件的 mode 属性控制裁剪方式,避免图片变形
  • 首屏图片优先加载,非首屏图片懒加载
xml 复制代码
<image
  src="{{item.cover}}"
  mode="aspectFill"
  lazy-load
  show-menu-by-longpress="{{false}}"
/>

6. API 与网络请求规范

6.1 请求封装

javascript 复制代码
// utils/request.js
import { BASE_URL, TOKEN_KEY } from '../config/constants'
import storage from './storage'

const request = (options) => {
  return new Promise((resolve, reject) => {
    const token = storage.get(TOKEN_KEY) || ''

    wx.request({
      url: BASE_URL + options.url,
      method: options.method || 'GET',
      data: options.data || {},
      header: {
        'Content-Type': 'application/json',
        'Authorization': token ? `Bearer ${token}` : '',
        ...options.header
      },
      timeout: 15000,

      success(res) {
        const { statusCode, data } = res

        // HTTP 状态码处理
        if (statusCode === 200) {
          // 业务状态码处理
          const { code, message, result } = data

          if (code === 0) {
            resolve(result)
          } else if (code === 401) {
            // 未登录,清除 token 并跳转登录
            storage.remove(TOKEN_KEY)
            wx.navigateTo({ url: '/pages/login/login' })
            reject(new Error('未登录'))
          } else {
            wx.showToast({ title: message || '请求失败', icon: 'none' })
            reject(new Error(message))
          }
        } else {
          wx.showToast({ title: '网络异常', icon: 'none' })
          reject(new Error(`HTTP ${statusCode}`))
        }
      },

      fail(err) {
        wx.showToast({ title: '网络连接失败', icon: 'none' })
        reject(err)
      }
    })
  })
}

export default {
  get: (url, data, options) => request({ url, method: 'GET', data, ...options }),
  post: (url, data, options) => request({ url, method: 'POST', data, ...options }),
  put: (url, data, options) => request({ url, method: 'PUT', data, ...options }),
  delete: (url, data, options) => request({ url, method: 'DELETE', data, ...options })
}

6.2 API 分层

javascript 复制代码
// api/modules/user.js
import request from '../../utils/request'

// 获取用户信息
export const getUserInfo = () => {
  return request.get('/api/user/info')
}

// 更新用户信息
export const updateUserInfo = (data) => {
  return request.post('/api/user/update', data)
}

// 上传头像
export const uploadAvatar = (filePath) => {
  return new Promise((resolve, reject) => {
    wx.uploadFile({
      url: BASE_URL + '/api/user/avatar',
      filePath,
      name: 'file',
      header: { Authorization: `Bearer ${token}` },
      success(res) {
        const data = JSON.parse(res.data)
        data.code === 0 ? resolve(data.result) : reject(data.message)
      },
      fail: reject
    })
  })
}
javascript 复制代码
// api/index.js
export * from './modules/user'
export * from './modules/order'
export * from './modules/goods'

6.3 请求规范

  • 所有接口调用必须经过 api/ 层,禁止在页面中直接 wx.request
  • GET 请求用于查询,POST 用于新增,PUT 用于更新,DELETE 用于删除
  • 接口参数必须做前端校验后再发送
  • 列表接口统一分页参数:pagepageSize
  • 加载状态统一管理,避免重复请求

7. 状态管理规范

7.1 方案选择

项目规模 推荐方案 说明
小型项目(< 20 页) 自实现简单 store 轻量,无依赖
中型项目 MobX-miniprogram 响应式,开发体验好
大型项目 Redux + 中间件 严格单向数据流,可追溯

7.2 简单 Store 实现

javascript 复制代码
// store/index.js
import { observable, autorun } from './observer'

class Store {
  constructor() {
    this.state = observable({
      user: {
        info: null,
        isLogin: false
      },
      cart: {
        count: 0,
        list: []
      }
    })
  }

  // 用户相关
  setUserInfo(info) {
    this.state.user.info = info
    this.state.user.isLogin = !!info
  }

  clearUser() {
    this.state.user.info = null
    this.state.user.isLogin = false
  }

  // 购物车相关
  setCartCount(count) {
    this.state.cart.count = count
  }
}

export default new Store()

7.3 使用规范

  • 全局共享数据才放入 store,页面私有数据放 data
  • 修改 state 必须通过 store 的方法,禁止直接修改
  • 页面订阅 store 变化时,在 onUnload 中取消订阅,防止内存泄漏

8. 样式规范

8.1 样式变量

css 复制代码
/* styles/variables.wxss */

/* 主题色 */
--color-primary: #ff6b35;
--color-primary-light: #ff8c5a;
--color-primary-dark: #e55a2b;

/* 辅助色 */
--color-success: #07c160;
--color-warning: #faad14;
--color-danger: #f5222d;
--color-info: #1890ff;

/* 文字颜色 */
--text-primary: #1a1a1a;
--text-regular: #333333;
--text-secondary: #666666;
--text-placeholder: #999999;
--text-disabled: #cccccc;

/* 背景色 */
--bg-page: #f5f5f5;
--bg-card: #ffffff;
--bg-mask: rgba(0, 0, 0, 0.5);

/* 边框色 */
--border-color: #eeeeee;
--border-color-light: #f5f5f5;

/* 间距 */
--spacing-xs: 8rpx;
--spacing-sm: 16rpx;
--spacing-md: 24rpx;
--spacing-lg: 32rpx;
--spacing-xl: 48rpx;

/* 圆角 */
--radius-sm: 8rpx;
--radius-md: 16rpx;
--radius-lg: 24rpx;
--radius-full: 9999rpx;

/* 字体大小 */
--font-size-xs: 20rpx;
--font-size-sm: 24rpx;
--font-size-md: 28rpx;
--font-size-lg: 32rpx;
--font-size-xl: 36rpx;

8.2 样式编写规范

  • 使用 rpx 作为尺寸单位(宽度相关),字体也用 rpx
  • 颜色统一使用 CSS 变量,禁止硬编码颜色值
  • 类名使用 BEM 命名法block__element--modifier
  • 禁止使用 ID 选择器、标签选择器(性能差)
  • 页面样式使用页面前缀隔离,避免污染全局
css 复制代码
/* ✅ 推荐 */
.goods-card {
  padding: var(--spacing-md);
  background: var(--bg-card);
  border-radius: var(--radius-md);
}

.goods-card__image {
  width: 200rpx;
  height: 200rpx;
  border-radius: var(--radius-sm);
}

.goods-card__title {
  font-size: var(--font-size-md);
  color: var(--text-primary);
  margin-top: var(--spacing-sm);
}

.goods-card__title--line2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

8.3 通用样式抽取

css 复制代码
/* styles/mixin.wxss */

/* 单行省略 */
.ellipsis {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* 多行省略 */
.ellipsis-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* flex 居中 */
.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 安全区域底部 */
.safe-bottom {
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

9. 性能优化规范

9.1 启动性能

  • 主包体积控制在 2MB 以内,总包不超过 20MB
  • 启用 lazyCodeLoading: "requiredComponents" 按需注入
  • 非首屏页面全部放入分包
  • 使用分包预下载,提前加载用户可能进入的分包
  • app.jsonLaunch 中只做必要的初始化,避免同步阻塞

9.2 渲染性能

  • setData 合并调用,避免频繁触发渲染
  • 只更新需要变化的数据,不要整个对象替换
  • 长列表使用 虚拟列表 或分页加载
  • 页面隐藏时停止定时器和动画
  • 合理使用 wx:ifhidden:频繁切换用 hidden,不频繁用 wx:if
javascript 复制代码
// ✅ 推荐:精确更新
this.setData({
  'list[0].count': newCount,
  'user.avatar': newAvatar
})

// ❌ 不推荐:整个替换
this.setData({
  list: newList,
  user: newUser
})

9.3 内存优化

  • 页面 onUnload 时清除定时器、事件监听
  • 及时取消未完成的请求
  • 大图及时释放,避免内存泄漏
  • 减少全局变量的使用

10. 安全规范

10.1 数据安全

  • 敏感信息(token、用户隐私)禁止存入 wx.setStorageSync,使用加密存储
  • 接口请求统一加签名,防止篡改
  • 用户输入必须做 XSS 过滤,rich-text 组件使用时必须校验内容
  • 禁止在前端硬编码密钥、密码等敏感信息

10.2 权限安全

  • 所有需要登录的页面必须做鉴权校验
  • 敏感操作(支付、删除)二次确认
  • 接口权限由后端控制,前端只做展示层控制

10.3 代码安全

  • 禁止使用 evalnew Function 等动态执行代码
  • 小程序发布前必须通过安全检测
  • 第三方 SDK 必须审核来源,禁止使用来源不明的代码

附录:AI 开发 Checklist

AI 在生成代码时,必须逐项检查以下内容:

  • 目录结构是否符合规范,文件命名是否正确
  • JS 代码是否使用 ES6+ 语法,是否有 var
  • 页面/组件方法顺序是否规范
  • 页面跳转是否使用统一封装的 navigator
  • 是否有硬编码的页面路径
  • 组件是否按分类放置,properties 是否规范
  • 自定义事件命名是否语义清晰
  • 图片资源是否使用 CDN 地址
  • 样式是否使用 CSS 变量,类名是否符合 BEM
  • 网络请求是否经过 api 层封装
  • 是否有未处理的异常和错误边界
  • 是否有性能问题(频繁 setData、内存泄漏)

最后更新 :2026-08-09

维护者 :前端团队

版本:v1.0.0

相关推荐
show4331 小时前
多格式导出怎么做?2026免费小程序TXT/SRT实践
开发语言·小程序·c#
孙启超1 小时前
Token太贵自己写了一个mac版开源AI编程工具
人工智能·macos·开源·llm·agent·ai编程·ai应用开发
jarvisuni1 小时前
翻车了!GPT5.6接手Opus4.8的项目之后!
前端·人工智能·ai编程
钱六两1 小时前
#9、如何使用SpringAI实现自主规划智能体
ai编程
fhhdzw2 小时前
别让 AI 替你理解代码
ai编程
前端小付2 小时前
我做了一个多 Agent 智能协作软件:让 AI 不再单打独斗
ai编程
山间小僧13 小时前
「AI学习笔记」Loop Engineering 和 Graph Engineering
langchain·agent·ai编程
大侠Luffy13 小时前
我开源了一个 Agent Skill:一键把播客生成小红书帖子
agent·ai编程·vibecoding
Jackson__13 小时前
从 LLM 到 Agent:一篇文章搞懂 AI 圈热词!
前端·agent·ai编程