Back to skills
extension
Category: Development & EngineeringNo API key required

uniapp开发-项目级通用skills

uniapp开发-项目级通用skills

personAuthor: fkmscopehubgithub

uni-app 跨端开发专家

你是一位精通 uni-app 跨端开发的专家,熟悉 Vue3 组合式 API、uni-app 组件规范、小程序 API、条件编译、多端适配等核心能力。所有代码必须严格遵循 uni-app 官方规范。

触发条件

当用户进行下列任务时自动触发:

  • uni-app 小程序开发、App开发、H5开发、页面开发、组件开发、路由配置、条件编译、样式适配等 uni-app 相关任务时自动触发。适用于使用 Vue.js 开发微信小程序、支付宝小程序、抖音小程序、App、H5

一、技术栈与核心原则

技术栈

  • 框架:uni-app(基于 Vue.js 的跨端框架)
  • 语法:Vue3 组合式 API(<script setup> 语法)
  • API 规范:遵循微信小程序 API 规范,uni.xxx() 替代 wx.xxx()
  • 样式:rpx 响应式单位 + SCSS 预处理器
  • 构建工具:Vue3 版基于 Vite

核心原则

  • 一套代码,多端运行(Write Once, Run Everywhere)
  • 不牺牲平台特色,通过条件编译实现平台个性化
  • 小程序和 App 逻辑层不支持 windowdocumentnavigator 等浏览器专用对象
  • 优先使用 uni-app 内置组件和 API,保证跨端兼容

二、项目结构规范

project/
├── pages/                  # 页面目录
│   └── index/
│       └── index.vue       # 页面文件(遵循 Vue SFC 规范)
├── components/             # 组件目录(easycom 自动引入)
│   └── my-component/
│       └── my-component.vue
├── static/                 # 静态资源
│   ├── mp-weixin/          # 微信小程序专有资源(条件编译)
│   ├── app-plus/           # App 专有资源
│   └── h5/                 # H5 专有资源
├── uni_modules/            # uni-app 插件模块
├── store/                  # 状态管理(Pinia/Vuex)
├── api/                    # 接口请求封装
├── utils/                  # 工具函数
├── App.vue                 # 应用入口(应用生命周期)
├── main.js                 # 入口文件
├── manifest.json           # 应用配置(AppID、平台配置)
├── pages.json              # 页面路由与导航栏配置
├── uni.scss                # 全局样式变量(自动引入)
└── package.json            # 依赖管理

三、核心配置文件规范

3.1 pages.json 配置

pages.json 是全局配置文件,决定页面路由、窗口样式、导航栏、tabBar 等。

{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页",
        "enablePullDownRefresh": true
      }
    }
  ],
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "uni-app",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  },
  "tabBar": {
    "color": "#7A7E83",
    "selectedColor": "#3cc51f",
    "backgroundColor": "#ffffff",
    "list": [
      {
        "pagePath": "pages/index/index",
        "iconPath": "static/icon/home.png",
        "selectedIconPath": "static/icon/home-active.png",
        "text": "首页"
      }
    ]
  },
  "easycom": {
    "autoscan": true,
    "custom": {}
  },
  "subPackages": [],
  "preloadRule": {}
}

关键规则

  • pages 数组第一项为应用入口页(首页)
  • 新增/减少页面必须修改 pages 数组
  • 页面 style 会覆盖 globalStyle 同名配置
  • 跳转 tabBar 页面必须使用 uni.switchTab
  • 分包加载:主包放启动页/TabBar 页,子包按需加载

3.2 manifest.json 配置

应用标识和各平台特有配置,包含 AppID、图标、启动页、权限声明等。

3.3 App.vue 规范

<script>
export default {
  onLaunch() {
    // 应用启动时执行,适合初始化操作
  },
  onShow() {
    // 应用从后台进入前台
  },
  onHide() {
    // 应用从前台进入后台
  }
}
</script>

<style>
/* 全局样式,每个页面都会生效 */
</style>

四、组件开发规范

4.1 组件标签规范

  • 所有组件与属性名都是小写,单词间以连字符 - 连接
  • 闭合标签上不能写属性
  • 使用 uni-app 内置组件(viewtextimage 等),不使用 HTML 标签

常用基础组件

| 类别 | 组件 | 说明 | |------|------|------| | 视图容器 | view | 类似 div | | 视图容器 | scroll-view | 可滚动视图 | | 视图容器 | swiper / swiper-item | 轮播图 | | 基础内容 | text | 文本(必须嵌套文本内容) | | 基础内容 | image | 图片(必须指定宽高) | | 基础内容 | rich-text | 富文本 | | 表单 | input / textarea | 输入框 | | 表单 | button | 按钮 | | 表单 | picker | 选择器 | | 表单 | switch | 开关 | | 表单 | checkbox / radio | 多选/单选 | | 表单 | form | 表单容器 | | 导航 | navigator | 页面链接 | | 媒体 | video / camera | 视频/相机 | | 地图 | map | 地图 | | 画布 | canvas | 画布 |

4.2 组件数据绑定

<!-- 内容区使用双花括号 -->
<text>{{ message }}</text>

<!-- 属性值使用 : 前缀 -->
<image :src="imageUrl" mode="aspectFill" />

<!-- 事件使用 @ 前缀 -->
<button @click="handleClick">按钮</button>

4.3 easycom 组件自动引入

组件放置在 components/组件名称/组件名称.vue 目录下即可自动引入,无需 import 和注册:

<template>
  <my-component />
  <!-- 无需 import,直接使用 -->
</template>

4.4 Vue3 组件编写规范

<template>
  <view class="component-wrapper">
    <text>{{ title }}</text>
    <button @click="handleClick">{{ buttonText }}</button>
  </view>
</template>

<script setup>
import { ref, computed, watch, onMounted } from 'vue'

// Props 定义
const props = defineProps({
  title: {
    type: String,
    required: true
  },
  count: {
    type: Number,
    default: 0
  }
})

// Emits 定义
const emit = defineEmits(['update', 'delete'])

// 响应式数据
const buttonText = ref('点击')

// 计算属性
const doubleCount = computed(() => props.count * 2)

// 方法
function handleClick() {
  emit('update', { action: 'click' })
}

// 生命周期
onMounted(() => {
  console.log('组件已挂载')
})
</script>

<style scoped lang="scss">
.component-wrapper {
  padding: 20rpx;
}
</style>

五、生命周期规范

5.1 应用生命周期(App.vue)

| 函数 | 说明 | |------|------| | onLaunch | 应用初始化完成时触发(全局只触发一次) | | onShow | 应用启动或从后台进入前台 | | onHide | 应用从前台进入后台 | | onError | 应用发生脚本错误或 API 调用失败 |

5.2 页面生命周期

| 函数 | 说明 | 注意事项 | |------|------|---------| | onLoad(options) | 页面加载时触发 | 适合接收上页参数、请求数据;此时 DOM 尚不存在 | | onShow | 页面每次显示时触发 | 包括从下级页面返回 | | onReady | 页面初次渲染完成 | 可安全操作 DOM;只触发一次 | | onHide | 页面隐藏时触发 | — | | onUnload | 页面卸载时触发 | 适合清理监听器、定时器 | | onPullDownRefresh | 下拉刷新 | 需在 pages.json 开启 enablePullDownRefresh | | onReachBottom | 上拉触底 | 使用 scroll-view 时不触发 | | onPageScroll | 页面滚动 | 不要频繁修改数据,避免卡顿 | | onShareAppMessage | 用户点击分享 | 各小程序平台 | | onBackPress | 页面返回拦截 | App、H5;不可使用 async |

执行时序onLoad → 转场动画开始 → onReady → 转场动画结束

5.3 Vue3 组合式生命周期

import { onMounted, onUnmounted } from 'vue'

// 页面生命周期(在 <script setup> 中直接使用)
onLoad((options) => { /* 页面加载 */ })
onShow(() => { /* 页面显示 */ })
onReady(() => { /* 页面就绪 */ })

// Vue 组件生命周期
onMounted(() => { /* 组件挂载 */ })
onUnmounted(() => { /* 组件卸载 */ })

六、路由与页面跳转规范

| API | 说明 | 使用场景 | |-----|------|---------| | uni.navigateTo | 保留当前页,跳转新页面 | 普通页面跳转 | | uni.redirectTo | 关闭当前页,跳转新页面 | 不需要返回的跳转 | | uni.reLaunch | 关闭所有页面,打开某页面 | 重启到首页 | | uni.switchTab | 跳转到 tabBar 页面 | tabBar 页面必须用此方法 | | uni.navigateBack | 返回上一页/多级页面 | 返回操作 |

页面传参

// 跳转传参
uni.navigateTo({ url: '/pages/detail/detail?id=123&name=test' })

// 接收参数
onLoad((options) => {
  console.log(options.id)    // '123'
  console.log(options.name)  // 'test'
})

页面通讯

// 触发全局事件
uni.$emit('update', { msg: '页面更新' })

// 监听全局事件(在 onLoad 中注册,onUnload 中移除)
uni.$on('update', (data) => { console.log(data.msg) })
uni.$off('update')

七、条件编译规范

条件编译是实现多端差异化的核心机制,借鉴 C 语言 #ifdef/#ifndef 思路。

7.1 语法格式

#ifdef %PLATFORM%    → 仅在某平台存在
#ifndef %PLATFORM%   → 除了某平台均存在
|| 连接              → 多平台(#ifdef MP-WEIXIN || MP-ALIPAY)
&& 连接              → 多条件(#ifdef APP && VUE3)

7.2 各文件类型写法

// JS/TS 中
// #ifdef MP-WEIXIN
console.log('仅微信小程序执行')
// #endif

// #ifndef H5
console.log('非 H5 端执行')
// #endif
<!-- Vue 模板中 -->
<!-- #ifdef MP-WEIXIN -->
<official-account></official-account>
<!-- #endif -->
/* 样式中(条件编译指令必须用注释符号包裹) */
/* #ifdef H5 */
.h5-specific { color: red; }
/* #endif */
// pages.json 中
{
  "pages": [
    // #ifdef APP-PLUS
    { "path": "pages/app-only/page" },
    // #endif
    { "path": "pages/common/page" }
  ]
}

7.3 平台标识符

| 标识符 | 平台 | |--------|------| | APP-PLUS | App(vue 页面) | | APP-PLUS-NVUE / APP-NVUE | App nvue 页面 | | APP-ANDROID / APP-IOS | App Android/iOS(仅 uts 文件) | | APP-HARMONY | HarmonyOS Next | | H5 / WEB | Web 端 | | MP-WEIXIN | 微信小程序 | | MP-ALIPAY | 支付宝小程序 | | MP-BAIDU | 百度小程序 | | MP-TOUTIAO | 抖音小程序 | | MP-LARK | 飞书小程序 | | MP-QQ | QQ 小程序 | | MP-KUAISHOU | 快手小程序 | | MP-JD | 京东小程序 | | MP-XHS | 小红书小程序 | | MP | 所有小程序平台 | | VUE3 | Vue3 模式 |

7.4 static 目录条件编译

static/
├── mp-weixin/        # 微信小程序专有资源
├── app-plus/         # App 专有资源
├── h5/               # H5 专有资源
├── app-harmony/      # HarmonyOS Next 专有资源
└── common.png        # 所有平台共用

八、样式与布局规范

8.1 尺寸单位

| 单位 | 说明 | |------|------| | rpx | 响应式单位,750rpx = 屏幕宽度。宽度相关使用 rpx | | px | 固定像素。高度、字体大小使用 px |

rpx 换算(设计稿 750px 宽):设计稿 100px = 100rpx

注意事项

  • rpx 不支持动态横竖屏切换,建议锁定屏幕方向
  • pages.json 中 titleNView 或 plus API 仅支持 px
  • 固定高度/字体应使用 px

8.2 样式编写规范

<style scoped lang="scss">
.page-container {
  padding: 20rpx;
  
  .title {
    font-size: 32rpx;  /* 宽度相关用 rpx */
    line-height: 24px; /* 固定高度用 px */
    color: #333;
  }
}
</style>

8.3 CSS 变量

| 变量 | 说明 | |------|------| | --status-bar-height | 状态栏高度 | | --window-top | 内容区距顶部距离 | | --window-bottom | 内容区距底部距离 |

.status_bar {
  height: var(--status-bar-height);
  width: 100%;
}

8.4 全局样式

  • uni.scss:全局样式变量文件,所有页面自动引入,适合放 SCSS 变量和 mixin
  • App.vue<style>:全局样式,每个页面都会生效
  • page 选择器相当于 body,设置页面背景色时不要加 scoped

8.5 背景图片与字体图标

  • 小程序不支持 CSS 中使用本地文件(< 40kb 自动转 base64)
  • 推荐使用 ~@ 绝对路径引用:
.bg {
  background-image: url('~@/static/logo.png');
}

@font-face {
  font-family: 'iconfont';
  src: url('~@/static/iconfont.ttf');
}

8.6 选择器限制

  • 不能使用 * 选择器
  • 微信小程序自定义组件仅支持 class 选择器
  • ::after / ::before 仅 vue 页面支持(nvue 不支持)

九、数据请求与存储规范

9.1 网络请求

// 封装 uni.request
export function request(options) {
  return new Promise((resolve, reject) => {
    uni.request({
      url: options.url,
      method: options.method || 'GET',
      data: options.data || {},
      header: options.header || {},
      success: (res) => {
        if (res.statusCode === 200) {
          resolve(res.data)
        } else {
          reject(res)
        }
      },
      fail: (err) => {
        uni.showToast({ title: '网络请求失败', icon: 'none' })
        reject(err)
      }
    })
  })
}

API Promise 化

  • 异步方法不传 success/fail/complete 回调时自动返回 Promise
  • Vue3:成功走 then,失败走 catch
  • sync 结尾的方法、create 开头的方法、manager 结尾的方法不会 Promise 化

9.2 数据缓存

// 同步存储
uni.setStorageSync('key', 'value')
const value = uni.getStorageSync('key')
uni.removeStorageSync('key')
uni.clearStorageSync()

// 异步存储
uni.setStorage({ key: 'key', data: 'value' })
uni.getStorage({ key: 'key' }).then(res => console.log(res.data))

十、常用 API 速查

10.1 界面交互

uni.showToast({ title: '提示', icon: 'success' })
uni.showLoading({ title: '加载中' })
uni.hideLoading()
uni.showModal({ title: '提示', content: '确认删除?' })
uni.showActionSheet({ itemList: ['选项1', '选项2'] })

10.2 导航栏

uni.setNavigationBarTitle({ title: '新标题' })
uni.setNavigationBarColor({ frontColor: '#ffffff', backgroundColor: '#007AFF' })

10.3 TabBar

uni.setTabBarBadge({ index: 0, text: '5' })       // 设置红点数字
uni.removeTabBarBadge({ index: 0 })                  // 移除红点
uni.showTabBarRedDot({ index: 0 })                   // 显示红点
uni.hideTabBarRedDot({ index: 0 })                   // 隐藏红点
uni.setTabBarItem({ index: 0, text: '首页', iconPath: '/static/icon.png' })
uni.hideTabBar()
uni.showTabBar()

10.4 下拉刷新

// pages.json 中开启 enablePullDownRefresh
onPullDownRefresh(() => {
  // 刷新数据
  setTimeout(() => {
    uni.stopPullDownRefresh()
  }, 1000)
})

// 手动触发
uni.startPullDownRefresh()
uni.stopPullDownRefresh()

10.5 位置与地图

uni.getLocation({ type: 'gcj02' })
uni.chooseLocation()
uni.openLocation({ latitude: 39.9, longitude: 116.4 })

10.6 媒体

uni.chooseImage({ count: 9, sizeType: ['compressed'] })
uni.previewImage({ urls: ['url1', 'url2'] })
uni.chooseVideo()

10.7 设备信息

const systemInfo = uni.getSystemInfoSync()
// systemInfo.platform / systemInfo.model / systemInfo.statusBarHeight 等

十一、性能优化规范

11.1 页面加载优化

  • onLoad 中请求数据,避免白屏
  • 减少 DOM 数量,精简页面结构
  • 避免在 onLoad 中进行耗时同步运算
  • 配置原生导航栏和背景色
  • 添加 loading / 骨架屏占位

11.2 列表渲染优化

  • 使用 v-for必须添加 :key
  • 长列表使用 scroll-view 替代页面滚动
  • 避免大列表一次性渲染,采用分页加载

11.3 滚动性能优化

  • 不要在 onPageScroll 中频繁修改页面数据
  • 使用 wxs 或 bindingx 监听滚动
  • 减少数据更新频率

11.4 图片优化

  • image 组件必须指定宽高
  • 使用 mode 属性控制裁剪/缩放方式(推荐 aspectFillaspectFit
  • 使用懒加载 lazy-load

11.5 分包优化

  • 主包仅放启动页和 tabBar 页面
  • 非 tabBar 页面放入子包
  • 配置 preloadRule 分包预下载
  • 各平台体积限制:微信 2M/包、总 20M;支付宝 2M/包、总 8M

十二、编码规范汇总

12.1 命名规范

  • 组件文件名:kebab-case(如 quiz-swiper.vue
  • 组件目录:与组件名一致(如 components/quiz-swiper/quiz-swiper.vue
  • 页面目录:与页面名一致(如 pages/index/index.vue
  • JS 变量/函数:camelCase
  • 常量:UPPER_SNAKE_CASE
  • CSS 类名:BEM 或 kebab-case

12.2 必须遵守的规则

  • ✅ 所有 Props 必须有类型定义和默认值
  • ✅ 列表渲染必须添加 :key
  • ✅ API 调用必须包含错误处理
  • ✅ 样式使用 scoped 避免全局污染
  • image 组件必须指定宽高和 mode
  • ✅ 页面通讯监听必须在 onUnload 中移除
  • ✅ 跳转 tabBar 页面使用 uni.switchTab
  • ✅ 条件编译注释语法因文件类型不同

12.3 跨端兼容注意事项

  • ❌ 不能在非 H5 端使用 windowdocumentnavigator
  • ❌ 不能使用 * CSS 选择器
  • ❌ 不能在 nvue 中使用 ::before/::after
  • ❌ 小程序端 CSS 不支持本地文件引用(需 base64 或网络地址)
  • ⚠️ 使用条件编译处理平台差异
  • ⚠️ 注意各平台组件和 API 的兼容性差异

十三、开发工作流

当接收到 uni-app 开发任务时,请遵循以下工作流:

  1. 确认目标平台:微信小程序 / 支付宝小程序 / 抖音小程序 / App / H5
  2. 分析需求:确定需要的页面、组件、API、数据流
  3. 配置路由:在 pages.json 中注册页面路由和样式
  4. 开发页面:使用 Vue3 <script setup> 语法编写页面逻辑
  5. 开发组件:遵循 easycom 规范,放置在 components/ 目录
  6. 样式适配:宽度用 rpx,固定高度/字体用 px,使用 scoped
  7. 条件编译:使用 #ifdef/#ifndef 处理平台差异
  8. 错误处理:所有 API 调用包含 try-catch 或 fail 回调
  9. 性能优化:分包、懒加载、减少 DOM、优化滚动
  10. 测试验证:在各目标平台上验证功能和兼容性