移动端开发规范 (Mobile App Development)
定位:uni-app x 跨平台移动应用开发标准,一套代码多端发布,确保高性能、可维护。
技术选型
| 层级 |
技术栈 |
版本要求 |
选型理由 |
| 框架 |
uni-app x |
≥ 4.0 |
基于 Vue 3、原生渲染、一套代码多端发布 |
| 开发语言 |
uts (Uni Type Script) |
- |
类型安全、编译到原生、性能接近原生 |
| UI 组件 |
uni-ui / uView |
最新 |
官方/社区组件库,跨端兼容 |
| 状态管理 |
Pinia |
≥ 2.0 |
Vue 3 官方推荐、TS 支持好 |
| 网络请求 |
uni.request 封装 |
- |
统一请求/响应处理 |
| 开发工具 |
HBuilderX |
最新 |
官方 IDE、调试方便 |
发布平台
| 平台 |
说明 |
| Android |
原生 APK,性能接近原生 |
| iOS |
原生 IPA,需 Mac 环境打包 |
| 微信小程序 |
编译为小程序代码 |
| H5 |
Web 应用 |
核心优势:uni-app x 使用 uts 语言,编译为原生代码(Kotlin/Swift),性能远超传统 uni-app。
项目结构
MyApp/
├── pages/ # 页面目录
│ ├── index/ # 首页
│ │ └── index.uvue
│ ├── user/ # 用户模块
│ │ └── profile.uvue
│ └── ...
├── pagesA/ # 分包 A
├── pagesB/ # 分包 B
├── components/ # 公共组件
│ ├── base/ # 基础组件
│ └── business/ # 业务组件
├── composables/ # 组合式函数
│ └── useAuth.uts
├── stores/ # Pinia 状态管理
│ └── user.uts
├── api/ # API 接口
│ ├── request.uts # 请求封装
│ └── modules/ # 按模块拆分
├── utils/ # 工具函数
├── static/ # 静态资源
├── uni_modules/ # uni 插件
├── App.uvue # 应用入口
├── main.uts # 入口文件
├── pages.json # 页面配置
├── manifest.json # 应用配置
└── uni.scss # 全局样式变量
核心组件
| 组件 |
用途 |
说明 |
view |
布局容器 |
类似 div |
text |
文本显示 |
所有文本必须包裹 |
scroll-view |
滚动容器 |
可横向/纵向滚动 |
list |
长列表 |
大列表必须使用,高性能渲染 |
swiper |
轮播图 |
滑动切换容器 |
image |
图片 |
支持懒加载 |
input |
输入框 |
表单输入 |
button |
按钮 |
跨端样式统一 |
命名规范
| 类型 |
规范 |
示例 |
| 页面目录 |
小写 + 连字符 |
user-profile/ |
| 组件文件 |
小写 + 连字符 |
user-card.uvue |
| 变量/函数 |
camelCase |
getUserInfo |
| 常量 |
UPPER_SNAKE |
API_BASE_URL |
| 类型/接口 |
PascalCase |
UserInfo |
| 组合式函数 |
use 前缀 |
useAuth |
页面配置 (pages.json)
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页"
}
}
],
"subPackages": [
{
"root": "pagesA",
"pages": [
{
"path": "list/list",
"style": { "navigationBarTitleText": "列表" }
}
]
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#ffffff"
}
}
样式规范
rpx 响应式单位
/* 使用 rpx 适配不同屏幕 */
.container {
width: 750rpx; /* 满屏宽度(设计稿基准 750) */
padding: 32rpx;
font-size: 28rpx;
}
全局样式变量 (uni.scss)
/* uni.scss */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
$uni-spacing-sm: 16rpx;
$uni-spacing-md: 32rpx;
$uni-spacing-lg: 48rpx;
平台条件编译
/* #ifdef APP-ANDROID */
.container { padding-top: 44px; }
/* #endif */
/* #ifdef APP-IOS */
.container { padding-top: 50px; }
/* #endif */
/* #ifdef MP-WEIXIN */
.container { padding-top: 0; }
/* #endif */
状态管理 (Pinia)
定义 Store
// stores/user.uts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', () => {
const token = ref<string>('')
const userInfo = ref<UserInfo | null>(null)
const isLoggedIn = computed(() => !!token.value)
function setToken(newToken: string) {
token.value = newToken
}
function logout() {
token.value = ''
userInfo.value = null
}
return { token, userInfo, isLoggedIn, setToken, logout }
})
使用 Store
<script setup lang="uts">
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
const { userInfo, isLoggedIn } = storeToRefs(userStore)
</script>
网络请求封装
请求工具
// api/request.uts
interface RequestOptions {
url: string
method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
data?: any
showLoading?: boolean
}
interface ApiResponse<T> {
code: number
message: string
data: T
}
export async function request<T>(options: RequestOptions): Promise<ApiResponse<T>> {
const { url, method = 'GET', data, showLoading = true } = options
if (showLoading) {
uni.showLoading({ title: '加载中', mask: true })
}
return new Promise((resolve, reject) => {
uni.request({
url: API_BASE_URL + url,
method,
data,
success: (res) => {
resolve(res.data as ApiResponse<T>)
},
fail: (err) => {
uni.showToast({ title: '网络错误', icon: 'none' })
reject(err)
},
complete: () => {
if (showLoading) uni.hideLoading()
}
})
})
}
API 模块化
// api/modules/user.uts
import { request } from '../request'
export const userApi = {
getUser: (id: number) => request<UserInfo>({
url: `/user/${id}`
}),
updateUser: (data: UserUpdate) => request<UserInfo>({
url: '/user',
method: 'PUT',
data
})
}
性能优化
长列表优化
<template>
<!-- 使用 list 组件,虚拟列表渲染 -->
<list class="list" :enable-back-to-top="true">
<cell v-for="item in list" :key="item.id">
<item-card :item="item" />
</cell>
</list>
</template>
图片懒加载
<image :src="imageUrl" mode="aspectFill" lazy-load />
分包预加载
// pages.json
{
"preloadRule": {
"pages/index/index": {
"network": "all",
"packages": ["pagesA"]
}
}
}
条件编译
平台判断
// #ifdef APP-ANDROID
console.log('Android 平台')
// #endif
// #ifdef APP-IOS
console.log('iOS 平台')
// #endif
// #ifdef MP-WEIXIN
console.log('微信小程序')
// #endif
// #ifdef H5
console.log('H5 平台')
// #endif
平台差异化代码
<template>
<view>
<!-- #ifdef APP-ANDROID -->
<text>Android 专属功能</text>
<!-- #endif -->
</view>
</template>
原生插件开发
Android 原生插件 (Kotlin)
// uni_modules/my-plugin/android/src/main/kotlin/MyModule.kt
class MyModule : UTSComponent() {
@UniJSMethod
fun showToast(message: String) {
// 原生实现
}
}
iOS 原生插件 (Swift)
// uni_modules/my-plugin/ios/Sources/MyModule.swift
@objc(MyModule)
class MyModule: NSObject {
@objc func showToast(_ message: String) {
// 原生实现
}
}
开发环境要求
| 项目 |
要求 |
| HBuilderX |
最新正式版 |
| Node.js |
≥ 18(CLI 模式需要) |
| Android Studio |
最新版(Android 开发) |
| Xcode |
≥ 15(iOS 开发,仅 macOS) |
| 内存 |
最低 8GB,推荐 16GB |
常见陷阱
| 问题 |
原因 |
解法 |
| 样式不生效 |
使用了不支持的 CSS |
查阅 uni-app x 支持的样式列表 |
| 列表卡顿 |
使用 v-for 渲染大列表 |
使用 list + cell 组件 |
| 图片不显示 |
路径错误或未配置域名 |
检查路径、配置合法域名 |
| 编译报错 |
uts 语法问题 |
检查类型定义,使用严格类型 |
| 平台差异 |
未做条件编译 |
使用 #ifdef 处理差异 |
调试技巧
| 场景 |
方法 |
| App 端 |
HBuilderX 真机调试 |
| 小程序 |
微信开发者工具预览 |
| H5 |
浏览器控制台 |
| 网络请求 |
控制台 Network 面板 |
沉淀协议
| 场景 |
行动 |
| 组件复用 ≥ 2 次 |
提取到 components/base/ |
| API 调用模式重复 ≥ 3 次 |
封装到 api/modules/ |
| 状态逻辑重复 ≥ 2 次 |
提取到 stores/ 或 composables/ |
| 平台差异处理固化 |
更新本文档条件编译章节 |