适用版本: uni-app Vue2 / Vue3 通用
整理日期: 2026-07-13
用途: 新手编写 uni-app 代码时快速查阅
目录
- 页面结构
- 基础组件(标签)
- 表单组件
- 媒体组件
- 地图与定位
- 导航组件
- 视图容器
- 通用属性
- 事件绑定
- Vue 指令
- 样式单位
- 生命周期
- 常用 API
- 命名规范速查
一、页面结构
每个 .vue 文件必须包含三段式结构:
html
<template>
<!-- 模板:页面结构,类似 HTML -->
</template>
<script>
// 脚本:业务逻辑,使用 JavaScript
export default {
data() { return {} },
methods: {},
onLoad() {},
// ...
}
</script>
<style>
/* 样式:美化页面,类似 CSS */
</style>
可选属性
| 属性 | 作用 | 示例 |
|---|---|---|
| lang="ts" | 使用 TypeScript | <script lang="ts"> |
| scoped | 样式只作用于当前组件 | <style scoped> |
| lang="scss" | 使用 SCSS 预处理器 | <style lang="scss"> |
二、基础组件(标签)
2.1 视图容器
<view> --- 通用容器(相当于 HTML 的 <div>)
| 属性 | 类型 | 说明 | 示例 |
|---|---|---|---|
| class | String | 类名,用于样式绑定 | class="container" |
| style | String | 内联样式 | style="color: red;" |
| id | String | 唯一标识 | id="header" |
| hover-class | String | 点击时的样式类 | hover-class="active" |
| hover-start-time | Number | 按住多久出现点击态(ms) | hover-start-time="50" |
| hover-stay-time | Number | 手指松开后保留多久(ms) | hover-stay-time="400" |
| hover-stop-propagation | Boolean | 阻止冒泡 | hover-stop-propagation |
| animation | Object | 动画对象 | 见动画 API |
html
<view class="box" hover-class="box-hover" @click="handleClick">
内容
</view>
<scroll-view> --- 可滚动视图
| 属性 | 类型 | 说明 | 示例 |
|---|---|---|---|
| scroll-x | Boolean | 横向滚动 | scroll-x |
| scroll-y | Boolean | 纵向滚动 | scroll-y |
| scroll-top | Number/String | 竖向滚动条位置 | :scroll-top="scrollTop" |
| scroll-left | Number/String | 横向滚动条位置 | :scroll-left="scrollLeft" |
| scroll-into-view | String | 滚动到指定元素(需设 id) | scroll-into-view="item3" |
| scroll-with-animation | Boolean | 滚动动画过渡 | scroll-with-animation |
| enable-back-to-top | Boolean | iOS 点击顶部回到顶部 | enable-back-to-top |
| upper-threshold | Number/String | 距顶部多远触发 scrolltoupper | upper-threshold="50" |
| lower-threshold | Number/String | 距底部多远触发 scrolltolower | lower-threshold="50" |
| @scrolltoupper | Event | 滚动到顶部/左边触发 | @scrolltoupper="toUpper" |
| @scrolltolower | Event | 滚动到底部/右边触发 | @scrolltolower="toLower" |
| @scroll | Event | 滚动时触发 | @scroll="onScroll" |
html
<scroll-view scroll-y class="scroll-box" @scrolltolower="loadMore">
<view v-for="item in list" :key="item.id">{{item.name}}</view>
</scroll-view>
<swiper> / <swiper-item> --- 滑块视图容器(轮播图)
属性(swiper)
| 属性 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| indicator-dots | Boolean | 显示面板指示点 | false |
| indicator-color | String | 指示点颜色 | rgba(0,0,0,.3) |
| indicator-active-color | String | 当前指示点颜色 | #000000 |
| autoplay | Boolean | 自动切换 | false |
| current | Number | 当前所在滑块索引 | 0 |
| interval | Number | 自动切换时间间隔(ms) | 5000 |
| duration | Number | 滑动动画时长(ms) | 500 |
| circular | Boolean | 衔接滑动(循环) | false |
| vertical | Boolean | 纵向滑动 | false |
| previous-margin | String | 前边距 | "0px" |
| next-margin | String | 后边距 | "0px" |
| display-multiple-items | Number | 同时显示数量 | 1 |
| @change | Event | 切换时触发 | @change="onChange" |
| @animationfinish | Event | 动画结束触发 | @animationfinish="onFinish" |
html
<swiper class="swiper" autoplay circular interval="3000" @change="onSwiperChange">
<swiper-item v-for="(item, index) in banners" :key="index">
<image :src="item.image" mode="aspectFill" />
</swiper-item>
</swiper>
<movable-area> / <movable-view> --- 可移动区域
属性(movable-view)
| 属性 | 类型 | 说明 |
|---|---|---|
| direction | String | 移动方向:all / vertical / horizontal / none |
| inertia | Boolean | 惯性滑动 |
| out-of-bounds | Boolean | 可超出边界 |
| x / y | Number/String | 定义位置 |
| scale | Boolean | 支持双指缩放 |
| scale-min / scale-max | Number | 缩放最小 / 最大值 |
| @change | Event | 拖动时触发 |
| @scale | Event | 缩放时触发 |
2.2 基础内容
<text> --- 文本(相当于 HTML 的 <span>)
| 属性 | 类型 | 说明 | 示例 |
|---|---|---|---|
| selectable | Boolean | 文本可选中 | selectable |
| space | String | 显示连续空格:ensp / emsp / nbsp | space="ensp" |
| decode | Boolean | 解码 HTML 实体 | decode |
| user-select | Boolean | 用户长按可选中文本 | user-select |
html
<text class="title" selectable>{{title}}</text>
<text decode>< 显示小于号</text>
<rich-text> --- 富文本
| 属性 | 类型 | 说明 |
|---|---|---|
| nodes | Array / String | HTML 字符串或节点列表 |
| space | String | 空格处理方式 |
html
<rich-text :nodes="htmlContent"></rich-text>
<progress> --- 进度条
| 属性 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| percent | Number | 百分比 0-100 | 0 |
| show-info | Boolean | 显示百分比文字 | false |
| border-radius | Number/String | 圆角大小 | 0 |
| font-size | Number/String | 文字大小 | 16 |
| color | String | 进度条颜色 | #09BB07 |
| activeColor | String | 已选进度条颜色 | #09BB07 |
| backgroundColor | String | 未选进度条颜色 | #EBEBEB |
| active | Boolean | 动画效果 | false |
| active-mode | String | 动画模式:backwards / forwards | backwards |
| @activeend | Event | 动画完成触发 |
html
<progress percent="60" show-info active color="#007aff" />
<icon> --- 图标
| 属性 | 类型 | 说明 | 可选值 |
|---|---|---|---|
| type | String | 图标类型 | success / success_no_circle / info / warn / waiting / cancel / download / search / clear |
| size | Number/String | 图标大小 | 23 |
| color | String | 图标颜色 |
html
<icon type="success" size="26" color="#07c160" />
三、表单组件
3.1 <button> --- 按钮
| 属性 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| size | String | 按钮大小:default / mini | default |
| type | String | 按钮样式:primary / default / warn | default |
| plain | Boolean | 镂空按钮 | false |
| disabled | Boolean | 禁用 | false |
| loading | Boolean | 加载中状态 | false |
| form-type | String | 表单提交:submit / reset | |
| open-type | String | 开放能力(见下方) | |
| hover-class | String | 点击样式 | button-hover |
| hover-start-time | Number | 按住多久出现点击态 | 20 |
| hover-stay-time | Number | 保留多久 | 70 |
| @click | Event | 点击事件 | @click="onClick" |
| @getphonenumber | Event | 获取手机号回调(需 open-type) | |
| @getuserinfo | Event | 获取用户信息回调 | |
| @contact | Event | 客服消息回调 | |
| @error | Event | 开放能力失败回调 |
open-type 开放能力值:
| 值 | 说明 | 平台 |
|---|---|---|
| contact | 打开客服会话 | 微信小程序 |
| share | 触发转发 | 微信小程序 |
| getPhoneNumber | 获取手机号 | 微信小程序 |
| getUserInfo | 获取用户信息 | 微信小程序 |
| launchApp | 打开 App | 微信小程序 |
| openSetting | 打开授权设置页 | 微信小程序 |
| feedback | 打开意见反馈 | 微信小程序 |
| chooseAvatar | 选择头像 | 微信小程序 |
| agreePrivacyAuthorization | 同意隐私协议 | 微信小程序 |
html
<button type="primary" @click="handleSubmit">提交</button>
<button type="default" plain size="mini" disabled>小号镂空禁用</button>
<button type="warn" loading>加载中...</button>
3.2 <input> --- 输入框
| 属性 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| value | String/Number | 输入框初始内容 | |
| v-model | String/Number | 双向绑定(推荐) | |
| type | String | 输入类型 | text |
| password | Boolean | 密码输入 | false |
| placeholder | String | 占位提示文字 | |
| placeholder-style | String | 占位文字样式 | |
| placeholder-class | String | 占位文字样式类 | |
| disabled | Boolean | 禁用 | false |
| maxlength | Number | 最大长度 | 140 |
| cursor-spacing | Number | 光标与键盘距离 | 0 |
| focus | Boolean | 自动聚焦 | false |
| confirm-type | String | 键盘右下角按钮:send / search / next / go / done | done |
| confirm-hold | Boolean | 点击确认按钮不收起键盘 | false |
| selection-start | Number | 光标起始位置 | -1 |
| selection-end | Number | 光标结束位置 | -1 |
| @input | Event | 输入时触发 | @input="onInput" |
| @focus | Event | 聚焦时触发 | |
| @blur | Event | 失焦时触发 | |
| @confirm | Event | 点击完成按钮时触发 | |
| @keyboardheightchange | Event | 键盘高度变化 |
type 可选值:
| 值 | 说明 |
|---|---|
| text | 文本输入 |
| number | 数字输入 |
| idcard | 身份证输入 |
| digit | 带小数点数字 |
| tel | 电话输入 |
| safe-password | 密码安全输入 |
| nickname | 昵称输入 |
html
<input v-model="username" placeholder="请输入用户名" />
<input v-model="password" type="password" placeholder="请输入密码" />
<input v-model="phone" type="tel" maxlength="11" placeholder="请输入手机号" />
3.3 <textarea> --- 多行输入框
| 属性 | 类型 | 说明 |
|---|---|---|
| value / v-model | String | 内容 |
| placeholder | String | 占位文字 |
| disabled | Boolean | 禁用 |
| maxlength | Number | 最大长度(-1 不限制) |
| auto-height | Boolean | 自动增高 |
| fixed | Boolean | 固定在页面(避免键盘遮挡) |
| cursor-spacing | Number | 光标与键盘距离 |
| focus | Boolean | 自动聚焦 |
| @input / @focus / @blur | Event | 输入/聚焦/失焦事件 |
html
<textarea v-model="content" placeholder="请输入内容" auto-height maxlength="200" />
3.4 <checkbox> / <checkbox-group> --- 复选框
属性(checkbox)
| 属性 | 类型 | 说明 |
|---|---|---|
| value | String | 选中时触发 change 事件的值 |
| checked | Boolean | 是否选中 |
| disabled | Boolean | 禁用 |
| color | String | 选中颜色 |
属性(checkbox-group)
| 属性 | 类型 | 说明 |
|---|---|---|
| @change | Event | 选中项变化时触发 |
html
<checkbox-group @change="onCheckboxChange">
<label v-for="item in items" :key="item.value">
<checkbox :value="item.value" :checked="item.checked" />
{{item.name}}
</label>
</checkbox-group>
3.5 <radio> / <radio-group> --- 单选框
属性(radio)
| 属性 | 类型 | 说明 |
|---|---|---|
| value | String | 选中值 |
| checked | Boolean | 是否选中 |
| disabled | Boolean | 禁用 |
| color | String | 选中颜色 |
html
<radio-group @change="onRadioChange">
<label v-for="item in items" :key="item.value">
<radio :value="item.value" :checked="item.checked" />
{{item.name}}
</label>
</radio-group>
3.6 <switch> --- 开关
| 属性 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| checked / v-model | Boolean | 是否选中 | false |
| disabled | Boolean | 禁用 | false |
| type | String | 样式:switch / checkbox | switch |
| color | String | 选中颜色 | #04BE02 |
| @change | Event | 状态变化时触发 |
html
<switch v-model="isOpen" @change="onSwitchChange" />
<switch v-model="isOpen" color="#007aff" />
3.7 <slider> --- 滑动选择器
| 属性 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| min | Number | 最小值 | 0 |
| max | Number | 最大值 | 100 |
| step | Number | 步长 | 1 |
| value / v-model | Number | 当前值 | 0 |
| disabled | Boolean | 禁用 | false |
| activeColor | String | 已选择颜色 | #007aff |
| backgroundColor | String | 背景条颜色 | #e9e9e9 |
| block-size | Number | 滑块大小 | 28 |
| show-value | Boolean | 显示当前值 | false |
| @change | Event | 值变化时触发 | |
| @changing | Event | 拖动过程中触发 |
html
<slider v-model="volume" min="0" max="100" show-value activeColor="#ff6600" />
3.8 <picker> --- 选择器
| 属性 | 类型 | 说明 |
|---|---|---|
| mode | String | 选择器类型 |
| range | Array | 选择范围 |
| range-key | String | 当 range 是对象数组时,指定显示字段 |
| value / v-model | Number | 当前选中索引 |
| disabled | Boolean | 禁用 |
| start | String | 有效时间起始(mode=time/date) |
| end | String | 有效时间结束(mode=time/date) |
| fields | String | 选择粒度:year / month / day |
| @change | Event | 选中值改变时触发 |
mode 可选值:
| 值 | 说明 |
|---|---|
| selector | 普通选择器 |
| multiSelector | 多列选择器 |
| time | 时间选择器 |
| date | 日期选择器 |
| region | 省市区选择器 |
html
<picker mode="selector" :range="array" v-model="index" @change="onPickerChange">
<view>当前选择:{{array[index]}}</view>
</picker>
<picker mode="date" v-model="date" @change="onDateChange">
<view>日期:{{date}}</view>
</picker>
3.9 <form> --- 表单
| 属性 | 类型 | 说明 |
|---|---|---|
| report-submit | Boolean | 是否返回 formId(用于发送模板消息) |
| @submit | Event | 提交表单,button form-type="submit" 触发 |
| @reset | Event | 重置表单,button form-type="reset" 触发 |
html
<form @submit="onSubmit" @reset="onReset">
<input name="username" placeholder="用户名" />
<input name="password" password placeholder="密码" />
<button form-type="submit" type="primary">提交</button>
<button form-type="reset">重置</button>
</form>
四、媒体组件
4.1 <image> --- 图片
| 属性 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| src | String | 图片路径(必填) | |
| mode | String | 裁剪 / 缩放模式 | scaleToFill |
| lazy-load | Boolean | 懒加载 | false |
| show-menu-by-longpress | Boolean | 长按显示菜单 | false |
| @error | Event | 加载失败时触发 | |
| @load | Event | 加载完成时触发 |
mode 可选值:
| 值 | 说明 |
|---|---|
| scaleToFill | 不保持比例,拉伸填满 |
| aspectFit | 保持比例,长边填满,短边留白 |
| aspectFill | 保持比例,短边填满,长边裁剪 |
| widthFix | 宽度不变,高度自动变化 |
| heightFix | 高度不变,宽度自动变化 |
| top / bottom / left / right / center | 不缩放,只显示对应区域 |
html
<image src="/static/logo.png" mode="aspectFit" class="logo" />
<image :src="userAvatar" mode="aspectFill" class="avatar" @error="onImgError" />
4.2 <video> --- 视频
| 属性 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| src | String | 视频地址 | |
| autoplay | Boolean | 自动播放 | false |
| loop | Boolean | 循环播放 | false |
| muted | Boolean | 静音播放 | false |
| initial-time | Number | 初始播放位置 | 0 |
| controls | Boolean | 显示默认控件 | true |
| poster | String | 封面图地址 | |
| show-fullscreen-btn | Boolean | 显示全屏按钮 | true |
| @play / @pause / @ended | Event | 播放/暂停/结束事件 |
html
<video src="https://example.com/video.mp4" poster="/static/poster.jpg" controls class="video-player" @play="onPlay" @ended="onEnded" />
4.3 <audio> --- 音频
| 属性 | 类型 | 说明 |
|---|---|---|
| src | String | 音频地址 |
| loop | Boolean | 循环播放 |
| controls | Boolean | 显示控件 |
| poster | String | 封面图 |
| name | String | 音频名字 |
| author | String | 作者 |
| @play / @pause / @ended / @timeupdate | Event | 播放/暂停/结束/进度更新事件 |
4.4 <camera> --- 相机
| 属性 | 类型 | 说明 |
|---|---|---|
| mode | String | 模式:normal / scanCode |
| resolution | String | 分辨率:low / medium / high |
| device-position | String | 摄像头:front / back |
| flash | String | 闪光灯:auto / on / off |
| frame-size | String | 帧尺寸:small / medium / large |
| @error / @initdone / @scancode | Event | 错误/初始化完成/扫码成功事件 |
五、地图与定位
5.1 <map> --- 地图
| 属性 | 类型 | 说明 |
|---|---|---|
| longitude | Number | 中心经度 |
| latitude | Number | 中心纬度 |
| scale | Number | 缩放级别 3-20 |
| markers | Array | 标记点 |
| polyline | Array | 路线 |
| circles | Array | 圆 |
| controls | Array | 控件 |
| show-location | Boolean | 显示当前位置 |
| @markertap | Event | 点击标记点时触发 |
| @regionchange | Event | 视野变化时触发 |
html
<map style="width: 100%; height: 300px;" :latitude="latitude" :longitude="longitude" :markers="markers" show-location @markertap="onMarkerTap" />
六、导航组件
6.1 <navigator> --- 页面链接
| 属性 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| url | String | 跳转地址 | |
| open-type | String | 跳转方式 | navigate |
| delta | Number | 回退层级(open-type=navigateBack) | 1 |
| hover-class | String | 点击样式 | navigator-hover |
| hover-start-time | Number | 按住多久出现点击态 | 50 |
| hover-stay-time | Number | 保留多久 | 600 |
open-type 可选值:
| 值 | 说明 |
|---|---|
| navigate | 保留当前页,跳转到应用内页面 |
| redirect | 关闭当前页,跳转到应用内页面 |
| switchTab | 跳转到 TabBar 页面 |
| reLaunch | 关闭所有页面,打开应用内页面 |
| navigateBack | 返回上一页面或多级页面 |
| exit | 退出小程序(仅微信) |
html
<navigator url="/pages/detail/detail?id=123" hover-class="nav-hover">
去详情页
</navigator>
<navigator url="/pages/index/index" open-type="switchTab">
去首页Tab
</navigator>
七、视图容器(补充)
7.1 <cover-view> / <cover-image> --- 覆盖在原生组件上的视图
用于覆盖在 <map>、<video>、<canvas> 等原生组件之上。
html
<video src="xxx.mp4">
<cover-view class="controls">
<cover-image src="/static/play.png" @click="play" />
</cover-view>
</video>
7.2 <match-media> --- 媒体查询
html
<match-media min-width="300" max-width="600">
<view>只在 300-600px 宽度时显示</view>
</match-media>
7.3 <slot> --- 插槽
html
<!-- 子组件 -->
<view class="card">
<slot name="header"></slot>
<slot></slot> <!-- 默认插槽 -->
<slot name="footer"></slot>
</view>
<!-- 父组件使用 -->
<my-card>
<template v-slot:header><text>标题</text></template>
<template v-slot:default><text>内容</text></template>
<template v-slot:footer><text>底部</text></template>
</my-card>
八、通用属性
以下属性几乎所有组件都支持:
| 属性 | 类型 | 说明 | 示例 |
|---|---|---|---|
| id | String | 唯一标识 | id="myView" |
| class | String | 类名(可多个) | class="box active" |
| style | String | 内联样式 | style="color: red;" |
| hidden | Boolean | 是否隐藏 | hidden / :hidden="true" |
| data-* | Any | 自定义数据 | data-id="123" |
| @click / @tap | Event | 点击事件 | @click="onClick" |
| @longpress | Event | 长按事件 | @longpress="onLong" |
8.1 条件渲染
| 指令 | 说明 | 示例 |
|---|---|---|
| v-if | 条件为真时渲染 | <view v-if="isShow">显示</view> |
| v-else-if | v-if 的 else-if | <view v-else-if="type==='B'">B</view> |
| v-else | v-if 的 else | <view v-else>其他</view> |
| v-show | 切换 display 显示/隐藏 | <view v-show="isShow"></view> |
区别:v-if 是真正的条件渲染(不渲染 DOM),v-show 只是切换 CSS display 属性。
8.2 列表渲染
| 指令 | 说明 | 示例 |
|---|---|---|
| v-for | 循环渲染列表 | <view v-for="item in list" :key="item.id"> |
| :key | 唯一标识,提高渲染效率 | :key="item.id" 或 :key="index" |
html
<view v-for="(item, index) in list" :key="item.id">
{{index + 1}}. {{item.name}} - {{item.age}}岁
</view>
九、事件绑定
9.1 事件修饰符
| 修饰符 | 说明 | 示例 |
|---|---|---|
| .stop | 阻止事件冒泡 | @click.stop="onClick" |
| .prevent | 阻止默认行为 | @submit.prevent="onSubmit" |
| .capture | 使用捕获模式 | @click.capture="onClick" |
| .self | 只当事件从元素本身触发时 | @click.self="onSelf" |
| .once | 事件只触发一次 | @click.once="onOnce" |
9.2 按键修饰符
| 修饰符 | 说明 |
|---|---|
| .enter | 回车键 |
| .tab | Tab 键 |
| .delete / .backspace | 删除键 |
| .esc | Esc 键 |
| .space | 空格键 |
| .up / .down / .left / .right | 方向键 |
html
<input @keyup.enter="submitForm" />
<input @keydown.esc="cancelInput" />
9.3 常用触摸事件
| 事件 | 说明 | 适用组件 |
|---|---|---|
| @click / @tap | 点击 | 所有 |
| @longpress | 长按(350ms) | 所有 |
| @touchstart | 触摸开始 | 所有 |
| @touchmove | 触摸移动 | 所有 |
| @touchend | 触摸结束 | 所有 |
| @touchcancel | 触摸被打断 | 所有 |
html
<view @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd" @longpress="onLongPress" >
触摸我
</view>
十、Vue 指令
10.1 核心指令
| 指令 | 简写 | 说明 | 示例 |
|---|---|---|---|
| v-bind | : | 动态绑定属性 | :src="imgUrl"、:class="{active: isActive}" |
| v-on | @ | 绑定事件 | @click="handleClick" |
| v-model | --- | 双向数据绑定 | v-model="inputValue" |
| v-if | --- | 条件渲染 | v-if="isShow" |
| v-for | --- | 列表渲染 | v-for="item in list" |
| v-show | --- | 显示/隐藏 | v-show="isVisible" |
10.2 v-bind 绑定 class
html
<!-- 对象语法 -->
<view :class="{ active: isActive, 'text-danger': hasError }"></view>
<!-- 数组语法 -->
<view :class="[activeClass, errorClass]"></view>
<!-- 混合 -->
<view :class="['static-class', { active: isActive }]"></view>
10.3 v-model 修饰符
| 修饰符 | 说明 | 示例 |
|---|---|---|
| .lazy | 失焦或回车才更新 | v-model.lazy="msg" |
| .number | 转为数字 | v-model.number="age" |
| .trim | 去除首尾空格 | v-model.trim="username" |
十一、样式单位
| 单位 | 说明 | 适用场景 |
|---|---|---|
| rpx | 响应式像素,屏幕宽 750rpx | uni-app 推荐,适配所有屏幕 |
| px | 固定像素 | 边框(1px)、阴影等不需要适配的 |
| vw | 视口宽度的百分比 | 1vw = 视口宽度的 1% |
| vh | 视口高度的百分比 | 1vh = 视口高度的 1% |
| % | 百分比 | 相对父元素 |
| rem | 相对根元素字体大小 | 需要设置根字体 |
rpx 换算
| 设备 | 屏幕宽度 | 1rpx 对应 |
|---|---|---|
| iPhone 5/SE | 320px | 0.4267px |
| iPhone 6/7/8 | 375px | 0.5px |
| iPhone 6/7/8 Plus | 414px | 0.552px |
| iPhone X/XS/11 Pro | 375px | 0.5px |
| iPhone 12/13/14 | 390px | 0.52px |
设计稿换算:如果设计稿宽度是 750px,直接 1px = 1rpx 使用。
十二、生命周期
12.1 Vue 组件生命周期
创建阶段: beforeCreate → created
挂载阶段: beforeMount → mounted
更新阶段(数据变化时): beforeUpdate → updated
销毁阶段: beforeDestroy → destroyed (Vue3 中 destroyed 改为 unmounted)
| 生命周期 | 触发时机 | 常用场景 |
|---|---|---|
| beforeCreate | 实例初始化之前 | 极少使用 |
| created | 实例创建完成,数据已初始化 | 初始化数据、调用接口 |
| beforeMount | 挂载开始之前 | 极少使用 |
| mounted | 挂载完成,DOM 已渲染 | 操作 DOM、初始化图表 |
| beforeUpdate | 数据更新之前 | 获取更新前的 DOM 状态 |
| updated | 数据更新完成 | 数据更新后操作 DOM |
| beforeDestroy | 销毁之前 | 清除定时器、解绑事件 |
| destroyed | 销毁完成 | 清理工作 |
12.2 uni-app 页面生命周期
| 生命周期 | 触发时机 | 常用场景 |
|---|---|---|
| onLoad(options) | 页面加载,可接收参数 | 获取页面参数、初始化数据 |
| onShow() | 页面显示 | 刷新数据、恢复状态 |
| onReady() | 页面初次渲染完成 | 操作 DOM、获取元素尺寸 |
| onHide() | 页面隐藏 | 暂停视频、保存状态 |
| onUnload() | 页面卸载 | 清除定时器、释放资源 |
| onPullDownRefresh() | 下拉刷新 | 刷新列表数据 |
| onReachBottom() | 上拉触底 | 加载更多 |
| onPageScroll(e) | 页面滚动 | 监听滚动位置 |
| onShareAppMessage() | 用户点击分享 | 自定义分享内容 |
| onTabItemTap(e) | 点击 TabBar | Tab 切换统计 |
| onResize() | 窗口尺寸变化 | 适配横竖屏 |
| onAddToFavorites() | 添加到收藏 | 自定义收藏内容 |
12.3 App 生命周期(在 App.vue 中)
| 生命周期 | 触发时机 |
|---|---|
| onLaunch() | 应用初始化完成时触发(全局只触发一次) |
| onShow() | 应用启动或从后台进入前台 |
| onHide() | 应用从前台进入后台 |
| onError(msg) | 应用报错时触发 |
| onUniNViewMessage() | 监听 nvue 页面发送的消息 |
| onUnhandledRejection() | 监听未处理的 Promise 拒绝 |
| onPageNotFound() | 页面不存在时触发 |
12.4 生命周期触发顺序示例
打开页面时:
App.onLaunch
→ App.onShow
→ Vue.beforeCreate
→ Vue.created
→ Page.onLoad
→ Page.onShow
→ Vue.beforeMount
→ Page.onReady
→ Vue.mounted
离开页面时:
Page.onHide
→ Vue.beforeDestroy
→ Vue.destroyed
→ Page.onUnload
切换 Tab 时:
离开:Page.onHide
进入:Page.onShow
十三、常用 API
13.1 网络请求
js
// GET 请求
uni.request({
url: 'https://api.example.com/list',
method: 'GET',
data: { page: 1, size: 10 },
header: {
'Authorization': 'Bearer ' + uni.getStorageSync('token')
},
success: (res) => {
console.log(res.data)
},
fail: (err) => {
console.error(err)
},
complete: () => {
// 无论成功失败都会执行
}
})
// POST 请求(JSON)
uni.request({
url: 'https://api.example.com/login',
method: 'POST',
data: { username: 'admin', password: '123456' },
header: {
'Content-Type': 'application/json'
},
success: (res) => {}
})
// POST 请求(表单)
uni.request({
url: 'https://api.example.com/upload',
method: 'POST',
data: { name: 'test' },
header: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
13.2 上传 / 下载
js
// 上传文件
uni.uploadFile({
url: 'https://api.example.com/upload',
filePath: tempFilePath, // 本地文件路径
name: 'file',
formData: { user: 'test' },
success: (res) => {}
})
// 下载文件
uni.downloadFile({
url: 'https://example.com/file.pdf',
success: (res) => {
if (res.statusCode === 200) {
uni.saveFile({
tempFilePath: res.tempFilePath
})
}
}
})
13.3 页面导航
js
// 保留当前页,跳转到新页面
uni.navigateTo({
url: '/pages/detail/detail?id=123&name=test'
})
// 关闭当前页,跳转到新页面
uni.redirectTo({
url: '/pages/login/login'
})
// 关闭所有页面,打开新页面
uni.reLaunch({
url: '/pages/home/home'
})
// 跳转到 TabBar 页面
uni.switchTab({
url: '/pages/index/index'
})
// 返回上一页
uni.navigateBack({ delta: 1 })
// 返回多级
uni.navigateBack({ delta: 2 })
13.4 数据存储
js
// 同步存储
uni.setStorageSync('token', 'abc123')
uni.setStorageSync('userInfo', { name: '张三', age: 20 })
// 同步读取
const token = uni.getStorageSync('token')
const userInfo = uni.getStorageSync('userInfo')
// 同步删除
uni.removeStorageSync('token')
// 同步清空
uni.clearStorageSync()
// 异步存储
uni.setStorage({
key: 'token',
data: 'abc123',
success: () => {}
})
// 异步读取
uni.getStorage({
key: 'token',
success: (res) => {
console.log(res.data)
}
})
13.5 弹窗提示
js
// 提示框(自动消失)
uni.showToast({
title: '操作成功',
icon: 'success', // success / error / loading / none
duration: 2000 // 显示时长(ms)
})
// 加载中
uni.showLoading({
title: '加载中...',
mask: true // 是否显示遮罩层
})
uni.hideLoading()
// 确认框
uni.showModal({
title: '提示',
content: '确定要删除吗?',
showCancel: true,
cancelText: '取消',
confirmText: '确定',
confirmColor: '#007aff',
success: (res) => {
if (res.confirm) {
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
// 操作菜单
uni.showActionSheet({
itemList: ['拍照', '从相册选择'],
success: (res) => {
console.log('选中了第' + (res.tapIndex + 1) + '个')
}
})
13.6 界面交互
js
// 设置导航栏标题
uni.setNavigationBarTitle({ title: '新标题' })
// 设置导航栏颜色
uni.setNavigationBarColor({
frontColor: '#ffffff',
backgroundColor: '#007aff'
})
// 显示 / 隐藏导航栏加载动画
uni.showNavigationBarLoading()
uni.hideNavigationBarLoading()
// 下拉刷新
uni.startPullDownRefresh()
uni.stopPullDownRefresh()
// 滚动到顶部
uni.pageScrollTo({
scrollTop: 0,
duration: 300
})
// 滚动到指定元素
uni.createSelectorQuery()
.select('#target')
.boundingClientRect()
.exec((res) => {
uni.pageScrollTo({
scrollTop: res[0].top,
duration: 300
})
})
13.7 媒体相关
js
// 选择图片
uni.chooseImage({
count: 9, // 最多选择数量
sizeType: ['original', 'compressed'], // 原图 / 压缩
sourceType: ['album', 'camera'], // 相册 / 相机
success: (res) => {
console.log(res.tempFilePaths) // 图片路径数组
}
})
// 预览图片
uni.previewImage({
current: 'https://example.com/1.jpg', // 当前显示
urls: ['https://example.com/1.jpg', 'https://example.com/2.jpg']
})
// 保存图片到相册
uni.saveImageToPhotosAlbum({
filePath: tempFilePath
})
// 选择视频
uni.chooseVideo({
sourceType: ['album', 'camera'],
maxDuration: 60,
camera: 'back',
success: (res) => {
console.log(res.tempFilePath)
}
})
// 录音
uni.startRecord({
success: (res) => {
console.log(res.tempFilePath)
}
})
uni.stopRecord()
13.8 位置相关
js
// 获取当前位置
uni.getLocation({
type: 'wgs84', // wgs84 / gcj02
altitude: true, // 是否返回高度
success: (res) => {
console.log(res.latitude, res.longitude)
}
})
// 打开地图选择位置
uni.chooseLocation({
success: (res) => {
console.log(res.name, res.address, res.latitude, res.longitude)
}
})
// 打开地图查看位置
uni.openLocation({
latitude: 39.9,
longitude: 116.4,
name: '天安门',
address: '北京市东城区'
})
13.9 设备信息
js
// 获取系统信息
uni.getSystemInfo({
success: (res) => {
console.log(res.model) // 设备型号
console.log(res.platform) // 平台:ios / android
console.log(res.windowWidth) // 窗口宽度
console.log(res.windowHeight) // 窗口高度
console.log(res.statusBarHeight) // 状态栏高度
console.log(res.safeArea) // 安全区域
console.log(res.pixelRatio) // 像素比
}
})
// 同步获取
const info = uni.getSystemInfoSync()
// 获取网络状态
uni.getNetworkType({
success: (res) => {
console.log(res.networkType) // wifi / 4g / 3g / 2g / offline
}
})
// 监听网络变化
uni.onNetworkStatusChange((res) => {
console.log(res.isConnected, res.networkType)
})
// 打电话
uni.makePhoneCall({ phoneNumber: '10086' })
// 扫码
uni.scanCode({
success: (res) => {
console.log(res.result) // 扫码内容
}
})
// 设置剪贴板
uni.setClipboardData({
data: '复制的内容',
success: () => {
uni.showToast({ title: '复制成功' })
}
})
// 获取剪贴板
uni.getClipboardData({
success: (res) => {
console.log(res.data)
}
})
// 振动
uni.vibrateShort() // 短振动
uni.vibrateLong() // 长振动
13.10 登录与授权
js
// 微信登录(获取 code)
uni.login({
provider: 'weixin',
success: (res) => {
console.log(res.code) // 传给后端换取 openid
}
})
// 获取用户信息
uni.getUserInfo({
provider: 'weixin',
success: (res) => {
console.log(res.userInfo)
}
})
// 检查登录状态
uni.checkSession({
success: () => { console.log('登录有效') },
fail: () => { console.log('登录过期,需要重新登录') }
})
// 获取手机号(需 button open-type)
// 在 button 的 @getphonenumber 回调中获取 encryptedData 和 iv
13.11 支付
js
// 发起支付
uni.requestPayment({
provider: 'wxpay', // wxpay / alipay
orderInfo: {}, // 订单信息
success: (res) => {},
fail: (err) => {}
})
13.12 文件操作
js
// 保存文件
uni.saveFile({
tempFilePath: tempPath,
success: (res) => {
console.log(res.savedFilePath)
}
})
// 获取本地文件列表
uni.getSavedFileList({
success: (res) => {
console.log(res.fileList)
}
})
// 删除本地文件
uni.removeSavedFile({
filePath: savedFilePath
})
// 打开文档
uni.openDocument({
filePath: filePath,
fileType: 'pdf' // 可选:doc / xls / ppt / pdf / docx / xlsx / pptx
})
十四、命名规范速查
14.1 文件 / 文件夹命名
| 类型 | 规范 | 示例 |
|---|---|---|
| 页面文件夹 | 全小写,多个单词用连字符 | pages/login-page/login-page.vue |
| 组件文件夹 | 全小写,多个单词用连字符 | components/my-button/my-button.vue |
| 静态资源 | 全小写,多个单词用连字符 | static/app-icon.png |
| JS 文件 | 全小写,多个单词用连字符 | utils/http-request.js |
14.2 CSS 类名命名
| 规范 | 示例 | 说明 |
|---|---|---|
| 短横线连接(kebab-case) | .login-form、.user-avatar | CSS 标准规范 |
| BEM 命名法 | .block__element--modifier | 大型项目推荐 |
css
/* BEM 示例 */
.login-page {} /* Block */
.login-page__form {} /* Element */
.login-page__form--error {} /* Modifier */
.login-page__button--primary {}
14.3 JavaScript 命名
| 类型 | 规范 | 示例 |
|---|---|---|
| 变量 | 小驼峰 | userName、isLogin |
| 常量 | 全大写下划线 | MAX_COUNT、API_BASE_URL |
| 函数 / 方法 | 小驼峰,动词开头 | handleLogin()、getUserInfo()、fetchData() |
| 组件名 | 大驼峰 | LoginPage.vue、MyButton.vue |
| 类名 | 大驼峰 | UserService、HttpRequest |
| 布尔变量 | is / has / can 开头 | isLoading、hasError、canSubmit |
| 数组 | 复数形式 | users、itemList |
| 回调函数 | on / handle 开头 | onClick、handleSubmit |
14.4 Vue 特定命名
| 类型 | 规范 | 示例 |
|---|---|---|
| data 属性 | 小驼峰 | title、userInfo |
| methods 方法 | 小驼峰,动词开头 | handleLogin()、onLoad() |
| computed 计算属性 | 小驼峰,名词开头 | fullName、formattedPrice |
| watch 监听 | 与被监听属性同名 | watch: { userName() {} } |
| 事件名 | 小驼峰 | @click、@scrolltolower |
| 自定义事件 | 小驼峰 | this.$emit('formSubmit') |
| props 属性 | 小驼峰 | props: { userName: String } |
| emit 事件名 | 小驼峰 | this.$emit('update:value') |
十五、常见问题速查
Q1: rpx 和 px 怎么选?
需要适配不同屏幕的用 rpx(宽度、高度、间距、字体大小),不需要适配的用 px(1px 边框、阴影 blur 值)
Q2: v-if 和 v-show 怎么选?
频繁切换显示 / 隐藏 → v-show(性能更好),条件很少变化 → v-if(DOM 更干净)
Q3: uni.navigateTo 和 uni.redirectTo 怎么选?
需要返回上一页 → navigateTo,不需要返回(如登录后)→ redirectTo 或 reLaunch
Q4: 页面传参怎么接收?
onLoad(options) { console.log(options.id); // 字符串 console.log(options.name); // 字符串 // 注意:所有参数都是字符串,数字需要转换 const pageNum = parseInt(options.page) || 1 }
Q5: 如何阻止事件冒泡?
<view @click.stop="onChildClick"> 点击我不会触发父元素的 click </view>
Q6: 如何获取元素尺寸?
uni.createSelectorQuery() .select('#myElement') .boundingClientRect() .exec((res) => { console.log(res[0].width, res[0].height, res[0].top) })
Q7: 如何监听页面滚动?
在 pages.json 中开启:{"path":"pages/list/list","style":{"enablePullDownRefresh":true,"onReachBottomDistance":50}},在页面中:
export default { onPageScroll(e) { console.log(e.scrollTop) // 滚动位置 }, onReachBottom() { console.log('触底了,加载更多') }, onPullDownRefresh() { console.log('下拉刷新') uni.stopPullDownRefresh() // 停止刷新动画 } }
十六、常用 CSS 样式速查
16.1 布局
css
/* Flex 布局(最常用) */
.container {
display: flex;
flex-direction: row; /* row / column */
justify-content: center; /* flex-start / center / flex-end / space-between / space-around */
align-items: center; /* flex-start / center / flex-end / stretch */
flex-wrap: wrap; /* 是否换行 */
}
/* 子元素 */
.item {
flex: 1; /* 占据剩余空间 */
flex-shrink: 0; /* 不压缩 */
}
/* 绝对定位 */
.box {
position: relative; /* 父元素设置 */
}
.box-child {
position: absolute;
top: 0;
right: 40rpx;
}
/* 固定定位 */
.fixed-box {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
16.2 文字样式
css
.text {
font-size: 28rpx;
color: #333333;
font-weight: bold; /* normal / bold / 100-900 */
text-align: center; /* left / center / right / justify */
line-height: 1.5; /* 行高 */
letter-spacing: 2rpx; /* 字间距 */
text-decoration: underline; /* 下划线 */
white-space: nowrap; /* 不换行 */
overflow: hidden;
text-overflow: ellipsis; /* 省略号 */
display: -webkit-box;
-webkit-line-clamp: 2; /* 最多显示2行 */
-webkit-box-orient: vertical;
}
16.3 盒子样式
css
.box {
width: 100%;
height: 200rpx;
padding: 20rpx 30rpx; /* 上下 左右 */
margin: 10rpx auto; /* 上下 左右自动(居中) */
border: 1rpx solid #ddd;
border-radius: 16rpx; /* 圆角 */
background-color: #fff;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
box-sizing: border-box; /* 宽高包含 padding 和 border */
}
16.4 背景
css
.bg {
background-color: #f5f5f5;
background-image: url('/static/bg.png');
background-size: cover; /* cover / contain */
background-position: center;
background-repeat: no-repeat;
}
提示: 本手册建议配合 uni-app 官方文档使用,遇到不明确的属性时以官方文档为准。
祝学习顺利!