UniApp 开发规范
目录
1. 功能说明
概述
本文档规定 UniApp 端的开发规范,包括代码风格、组件使用、平台适配等方面。
适用场景
- UniApp 功能开发
- 跨平台适配
- 代码审查参考
2. 设计思路
规范目标
- 统一多端代码风格
- 提高跨平台兼容性
- 优化小程序性能
- 提升开发效率
3. 代码规范
3.1 文件命名规范
| 类型 | 命名方式 | 示例 |
|---|---|---|
| 页面文件 | kebab-case | user-setting.vue |
| 组件文件 | kebab-case | goods-card.vue |
| 工具文件 | camelCase | request.ts |
| 样式文件 | kebab-case | common-style.scss |
3.2 页面规范
页面结构
vue
<template>
<view class="page-user-setting">
<!-- 导航栏 -->
<nav-bar title="设置" />
<!-- 页面内容 -->
<view class="page-content">
<!-- 内容区域 -->
</view>
<!-- 底部操作 -->
<view class="page-footer">
<!-- 底部按钮等 -->
</view>
</view>
</template>
<script setup lang="ts">
import { ref, onLoad } from '@dcloudio/uni-app';
import NavBar from '@/components/nav-bar/nav-bar.vue';
// 页面数据
const loading = ref(false);
const userInfo = ref<UserInfo | null>(null);
// 生命周期
onLoad((options) => {
console.log('页面参数:', options);
fetchUserInfo();
});
// 方法
const fetchUserInfo = async () => {
loading.value = true;
try {
// 请求数据
} finally {
loading.value = false;
}
};
</script>
<style lang="scss" scoped>
.page-user-setting {
min-height: 100vh;
background-color: #f5f5f5;
.page-content {
padding: 20rpx;
}
.page-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx;
background-color: #fff;
}
}
</style>页面配置
json
// pages.json
{
"path": "pages/user/setting",
"style": {
"navigationBarTitleText": "设置",
"navigationBarBackgroundColor": "#fff",
"navigationBarTextStyle": "black",
"enablePullDownRefresh": true,
"onReachBottomDistance": 50
}
}3.3 组件规范
组件定义
vue
<template>
<view class="goods-card" @click="handleClick">
<image class="goods-image" :src="image" mode="aspectFill" />
<view class="goods-info">
<text class="goods-title">{{ title }}</text>
<text class="goods-price">¥{{ price }}</text>
</view>
</view>
</template>
<script setup lang="ts">
interface Props {
id: number;
title: string;
price: number;
image: string;
}
const props = withDefaults(defineProps<Props>(), {
price: 0
});
const emit = defineEmits<{
(e: 'click', id: number): void;
}>();
const handleClick = () => {
emit('click', props.id);
};
</script>
<style lang="scss" scoped>
.goods-card {
background-color: #fff;
border-radius: 12rpx;
overflow: hidden;
.goods-image {
width: 100%;
height: 300rpx;
}
.goods-info {
padding: 20rpx;
.goods-title {
font-size: 28rpx;
color: #333;
line-height: 1.4;
}
.goods-price {
font-size: 32rpx;
color: #ff4d4f;
font-weight: bold;
}
}
}
</style>3.4 API 封装规范
typescript
// src/api/member.ts
import { request } from '@/utils/request';
import type { MemberInfo, MemberUpdateParams } from './types';
/**
* 获取会员信息
*/
export function getMemberInfo() {
return request<MemberInfo>({
url: '/api/member/info',
method: 'GET'
});
}
/**
* 更新会员信息
* @param data 更新数据
*/
export function updateMemberInfo(data: MemberUpdateParams) {
return request({
url: '/api/member/info',
method: 'PUT',
data
});
}
/**
* 上传头像
* @param filePath 文件路径
*/
export function uploadAvatar(filePath: string) {
return request({
url: '/api/member/avatar',
method: 'POST',
filePath,
name: 'file'
});
}3.5 状态管理规范
typescript
// src/stores/modules/user.ts
import { defineStore } from 'pinia';
import { getMemberInfo } from '@/api/member';
import type { MemberInfo } from '@/api/types';
interface UserState {
info: MemberInfo | null;
token: string;
isLogin: boolean;
}
export const useUserStore = defineStore('user', {
state: (): UserState => ({
info: null,
token: uni.getStorageSync('token') || '',
isLogin: false
}),
actions: {
// 设置 Token
setToken(token: string) {
this.token = token;
this.isLogin = !!token;
uni.setStorageSync('token', token);
},
// 获取用户信息
async fetchUserInfo() {
try {
const res = await getMemberInfo();
this.info = res.data;
return res.data;
} catch (error) {
return Promise.reject(error);
}
},
// 退出登录
logout() {
this.token = '';
this.info = null;
this.isLogin = false;
uni.removeStorageSync('token');
}
}
});3.6 样式规范
rpx 使用
scss
/* 推荐:使用 rpx 适配不同屏幕 */
.container {
padding: 20rpx;
font-size: 28rpx;
}
/* 特殊场景使用 px */
.border {
border: 1px solid #eee;
}变量定义
scss
// src/styles/variables.scss
// 颜色变量
$primary-color: #2979ff;
$success-color: #19be6b;
$warning-color: #ff9900;
$error-color: #fa3534;
// 文字颜色
$text-color: #303133;
$text-color-secondary: #909399;
// 背景颜色
$bg-color: #f5f5f5;
$bg-color-white: #ffffff;
// 边框颜色
$border-color: #ebeef5;
// 字体大小
$font-size-sm: 24rpx;
$font-size-base: 28rpx;
$font-size-lg: 32rpx;3.7 平台适配规范
typescript
// src/utils/platform.ts
/**
* 平台判断
*/
export const isH5 = () => {
// #ifdef H5
return true;
// #endif
return false;
};
export const isWeixin = () => {
// #ifdef MP-WEIXIN
return true;
// #endif
return false;
};
export const isApp = () => {
// #ifdef APP-PLUS
return true;
// #endif
return false;
};
/**
* 获取平台特定配置
*/
export const getPlatformConfig = () => {
// #ifdef H5
return { uploadUrl: '/api/upload' };
// #endif
// #ifdef MP-WEIXIN
return { uploadUrl: 'https://api.example.com/upload' };
// #endif
// #ifdef APP-PLUS
return { uploadUrl: 'https://api.example.com/upload' };
// #endif
};4. 常见问题
Q1: 如何优化小程序包体积
解决方案:
- 使用分包加载
- 压缩图片资源
- 按需引入组件
- 删除无用代码
json
// pages.json
{
"subPackages": [
{
"root": "pages-sub/goods",
"pages": [...]
}
]
}Q2: 如何处理页面通信
typescript
// 页面 A - 发送数据
uni.navigateTo({
url: '/pages/b/index?id=1'
});
// 或使用事件总线
uni.$emit('updateData', { key: 'value' });
// 页面 B - 接收数据
onLoad((options) => {
console.log(options.id);
});
// 监听事件
onMounted(() => {
uni.$on('updateData', (data) => {
console.log(data);
});
});Q3: 如何实现下拉刷新和上拉加载
vue
<script setup lang="ts">
import { ref, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app';
const list = ref([]);
const page = ref(1);
const loading = ref(false);
const finished = ref(false);
// 下拉刷新
onPullDownRefresh(async () => {
page.value = 1;
finished.value = false;
await fetchList();
uni.stopPullDownRefresh();
});
// 上拉加载
onReachBottom(() => {
if (!finished.value && !loading.value) {
page.value++;
fetchList();
}
});
const fetchList = async () => {
loading.value = true;
try {
const res = await getList({ page: page.value });
if (page.value === 1) {
list.value = res.data;
} else {
list.value.push(...res.data);
}
finished.value = res.data.length < 10;
} finally {
loading.value = false;
}
};
</script>修订记录
| 版本 | 日期 | 修订人 | 修订内容 |
|---|---|---|---|
| v1.0 | 2026-04-08 | Niucloud Team | 初始版本 |
