希望对大家有帮助吧
下载工具
HBuilderX:www.dcloud.io/hbuilderx.h…
目录结构
uniapp-project/
├── pages/ # 页面
├── components/ # 组件
├── static/ # 静态资源【图片、css文件】
├── styles/ # 公共样式
├── utils/ # 工具函数
├── api/ # 接口请求
├── stores/ # 状态管理
├── const/ # 常量配置
├── mixins/ # 混入
├── App.vue # 整个uniapp项目的第一个组件
├── main.js # 第一个运行的js文件【全局js文件】
├── manifest.json # 全局文件=>应用的配置
├── pages.json # 全局文件=>页面的配置
└── uni.scss # 全局样式文件
环境搭建 / 平台运行
小程序平台
- 微信小程序
- 百度小程序
- 支付宝小程序
运行步骤:
- 下载对应的小程序开发者工具
- 运行项目
- web
- app(iOS 不再支持基座调试 → 使用模拟器 xCode;安卓可用 Android Studio)
条件编译
在不同的端展示不同的代码,实现"一套代码,多端差异配置"。 uniapp.dcloud.net.cn/tutorial/pl…
平台标识
#ifdef H5- 仅 H5 平台#ifndef H5- 除 H5 外#ifdef APP-PLUS- 仅 App 平台#ifdef MP-WEIXIN- 仅微信小程序#ifdef MP-ALIPAY- 仅支付宝小程序
app-plus(App 端特有)
只针对 App 端有效,在 H5 或小程序中会自动忽略。
常见用途:
- App 特有样式
- 原生能力调用
- 平台判断
使用示例
// app-plus 无法直接判断 iOS 还是 Android,需用:
const platform = uni.getSystemInfoSync().platform;
export default {
methods: {
doSomething() {
// #ifdef APP-PLUS
console.log('仅 App 端显示')
// #endif
// #ifdef H5
console.log('仅 H5 端显示')
// #endif
}
}
}
<template>
<view class="content">
<!-- #ifdef APP-PLUS -->
<button type="primary">App专属按钮</button>
<!-- #endif -->
<!-- #ifdef H5 -->
<button>H5专属按钮</button>
<!-- #endif -->
</view>
</template>
基本语法
建议学习 uniapp 之前先学习 vue 和微信小程序。
每一个 .vue 文件由三个部分组成:template script style
一、template:布局盒子(视图)
view- 类似于 divtext- 放入文字(可以加入属性让它选中)- 表单组件:
buttonforminputlabel
二、css
- 尺寸单位:
rpx- 响应式 px,UI 设计图宽度为 750 时,测量宽度 300px 写 300rpx
三、script
常用组件选项
- data - 组件数据,必须是返回对象的函数
data() {
return {
key: ''
}
}
- computed - 计算属性
computed: {
total() {
return this.items.reduce((sum, item) => sum + item.price, 0)
}
}
- watch - 监听属性
watch: {
keyword(newVal, oldVal) {
console.log('关键词变化:', oldVal, '->', newVal)
}
}
- methods - 方法
methods: {
goSearch() {
console.log(this.key)
}
}
- mounted - 生命周期钩子
mounted() {
console.log('组件已挂载')
}
组件
组件通讯
父传子
<!-- 父组件 -->
<child-component :message="parentMsg" />
<!-- 子组件 -->
props: {
message: {
type: String,
default: ''
}
}
子传父
<!-- 子组件 -->
<button @click="$emit('update', data)">发送</button>
<!-- 父组件 -->
<child-component @update="handleUpdate" />
兄弟组件通讯
// A 组件传
uni.$emit('update', data)
// B 组件接(通常在 onMounted 中监听,在 onUnload 中取消)
uni.$on('update', (data) => {
console.log(data)
})
easycom 自动导入
easycom 可以在页面中直接使用组件,不用手动 import 和注册。
使用规则:
- 组件放在
components/组件名/组件名.vue目录即可自动识别 - 配置位于 pages.json 顶部
{
"easycom": {
"autoscan": true,
"custom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
}
}
}
示例:
components/
├── my-button/my-button.vue → 可直接使用 <my-button />
├── u-button/u-button.vue → 需配置 custom 后使用 <u-button />
生命周期
uniapp 如何定义页面?
- 每次新建页面需在 pages.json 中配置 pages 列表
- 通过 HBuilderX 开发时,右键"新建页面"会自动注册
- .vue 文件拥有独立的生命周期
页面生命周期
onLoad- 第一次进入页面执行(场景:接收页面参数)onShow- 每次进入页面执行onReady- 页面渲染完成(场景:可以获取 dom)onHide- 页面隐藏onUnload- 页面卸载
下拉刷新
需在 pages.json 对应页面配置 "enablePullDownRefresh": true
onPullDownRefresh() {
console.log('触发下拉刷新')
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1000)
}
组件生命周期
与 Vue 组件生命周期相同:created mounted updated unmounted 等
路由页面跳转
API 方法
| 方法 | 说明 |
|---|---|
uni.navigateTo | 保留当前页面,跳转到其他页面 |
uni.redirectTo | 关闭当前页面,跳转到其他页面 |
uni.reLaunch | 关闭所有页面,打开到应用内的某个页面 |
uni.switchTab | 跳转到 tabBar 页面(必须用此方法) |
uni.navigateBack | 返回上一页面或多级页面 |
methods: {
goList() {
uni.navigateTo({ url: '/pages/list/list' })
}
}
组件方式
<navigator url="/pages/list/list" open-type="switchTab">跳转到list</navigator>
页面传值
URL 参数传值
// A 页面传
uni.navigateTo({
url: '/pages/search/search?key=' + this.key + '&id=111'
})
// B 页面接
onLoad(options) {
this.keyName = options.key
}
网络请求
async/await 封装示例
// utils/request.js
const request = (options) => {
return new Promise((resolve, reject) => {
uni.request({
url: options.url,
method: options.method || 'GET',
data: options.data || {},
success: (res) => resolve(res.data),
fail: (err) => reject(err)
})
})
}
// 页面中使用
async getList() {
try {
const res = await request({ url: '/api/list' })
this.list = res.data
} catch (e) {
uni.showToast({ title: '请求失败' })
}
}
状态管理
推荐使用 Pinia
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++
}
}
})
// 页面使用
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
counter.increment()
分包
当小程序代码包体积过大时,可使用分包优化。
{
"subPackages": [
{
"root": "pages-sub/",
"pages": [
{ "path": "detail/detail" }
]
}
]
}
pages.json 配置
pages 数组
- 第一项为应用入口页(首页)
- 新增/减少页面需修改 pages 数组
- 文件名不需要写后缀
tabBar 底部导航栏
| 属性 | 说明 |
|---|---|
color | 文字默认颜色 |
selectedColor | 选中时文字颜色 |
backgroundColor | 背景色 |
borderStyle | 上边框颜色(仅支持 black/white) |
midButton | 中间按钮(仅支持 App 和 H5) |
{
"pages": [
{ "path": "pages/index/index", "style": { "navigationBarTitleText": "首页" } }
],
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#007AFF",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/image/home.png",
"selectedIconPath": "static/image/home1.png"
}
]
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
}
}
常见问题
样式不生效
- 检查是否有
scoped样式 - 检查选择器是否正确
请求不发起
- 检查域名是否在白名单(小程序)
- 检查网络权限
页面不跳转
- 检查 pages.json 是否已注册页面
- tabBar 页面必须使用
switchTab