一、uniApp 精简速记版(打印背诵)
1. 核心概念
1. 一套代码多端:H5/各小程序/App安卓iOS
2. 开发工具:HBuilderX
3. 单位:rpx(750rpx=满屏宽)
4. 自动引入组件:easycom,components下组件直接使用
2. 核心配置文件速记
pages.json(路由/导航/tab/分包)
1. pages:数组首位=首页
2. window:全局导航栏样式,单页面style覆盖
3. tabBar:2~5个,switchTab跳转,不能带参数
4. subPackages:分包,解决2M主包限制
5. preloadRule:分包预加载提速
manifest.json
各端权限、Appid、图标、启动页、第三方key配置
App.vue
全局唯一,存放全局样式、应用生命周期
3. 生命周期(必背)
应用生命周期(App.vue)
onLaunch(仅一次) → onShow(前台) → onHide(后台) → onError
页面生命周期
onLoad(拿参数) → onShow(每次显示) → onReady(DOM完成) → onHide → onUnload(销毁)
页面专属钩子:
onPullDownRefresh 下拉刷新
onReachBottom 触底分页
onPageScroll 页面滚动
onShareAppMessage 小程序分享
组件生命周期
Vue2:created/mounted/destroyed
Vue3:setup/onMounted/onUnmounted
4. 路由5个API
1. navigateTo:新开页面,存页面栈,不能跳tab
2. redirectTo:关闭当前页跳转,无返回
3. reLaunch:清空所有页面,跳首页
4. switchTab:跳转tab页面,url不带参数
5. navigateBack(delta):返回n页
传参3种:url拼接、eventChannel复杂对象、storage/store全局
5. 高频uni API速记
本地缓存(同步)
setStorageSync / getStorageSync / removeStorageSync / clearStorageSync
弹窗
showToast轻提示、showLoading加载框、showModal确认弹窗、showActionSheet底部菜单
网络请求
uni.request,统一封装加token、loading、401登录跳转
媒体设备
chooseImage选图、uploadFile上传、previewImage预览大图、getSystemInfo获取设备尺寸
6. 组件通信
1. 父传子:props
2. 子传父:$emit
3. 全局共享:Vuex(Vue2) / Pinia(Vue3)
4. 跨页面临时传参:eventChannel
7. 条件编译(跨端兼容核心)
js
// #ifdef MP-WEIXIN 仅微信小程序
// #ifdef APP-PLUS 仅App
// #ifdef H5 仅网页
// #ifndef MP 排除所有小程序
// #endif
8. 性能优化速记
1. 分包拆分,主包只放首页tab
2. 长列表用虚拟列表
3. 页面销毁清除定时器、请求
4. 图片压缩懒加载
5. 减少onPageScroll内复杂逻辑
9. 高频坑点速记
1. tab切换switchTab不能拼接参数,用storage传值
2. js代码不能直接写rpx,需转px计算
3. 本地图片必须放static目录
4. 页面栈最多10层,多层跳转用reLaunch清空
5. 下拉刷新需pages.json手动开启
二、完整初始化项目模板(直接复制使用)
目录结构
plaintext
uni-template/
├── api # 接口统一管理
│ └── user.js
├── components # 全局公共组件
│ └── NavBar
├── pages # 页面
│ ├── index # 首页tab
│ ├── mine # 我的tab
│ └── login # 登录页
├── static # 图片、字体静态资源
├── store # 全局状态 Vue2 Vuex
├── subpages # 分包页面
│ └── order
├── utils # 工具类
│ └── request.js # 请求封装
├── App.vue
├── main.js
├── pages.json
└── manifest.json
1. utils/request.js 请求封装(通用)
js
const baseUrl = 'https://api.test.com'
const request = (options) => {
uni.showLoading({ title: '加载中...' })
const token = uni.getStorageSync('token')
return new Promise((resolve, reject) => {
uni.request({
url: baseUrl + options.url,
method: options.method || 'GET',
data: options.data || {},
header: {
'Content-Type': 'application/json',
token: token || ''
},
success: (res) => {
uni.hideLoading()
const data = res.data
if (data.code === 200) {
resolve(data)
} else if (data.code === 401) {
uni.clearStorageSync()
uni.reLaunch({ url: '/pages/login/login' })
} else {
uni.showToast({ title: data.msg, icon: 'none' })
reject(data)
}
},
fail: (err) => {
uni.hideLoading()
uni.showToast({ title: '网络异常', icon: 'none' })
reject(err)
}
})
})
}
export default request
2. api/user.js 接口示例
js
import request from '@/utils/request'
// 登录
export function login(data) {
return request({
url: '/user/login',
method: 'POST',
data
})
}
// 获取用户信息
export function getUserInfo() {
return request({
url: '/user/info'
})
}
3. pages.json 完整配置(tabBar + 分包)
json
{
"pages": [
"pages/index/index",
"pages/mine/mine",
"pages/login/login"
],
"subPackages": [
{
"root": "subpages",
"pages": ["order/order"]
}
],
"window": {
"navigationBarTitleText": "uniApp项目",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"backgroundColor": "#f6f6f6"
},
"tabBar": {
"color": "#999",
"selectedColor": "#007aff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/tab/home.png",
"selectedIconPath": "static/tab/home-active.png"
},
{
"pagePath": "pages/mine/mine",
"text": "我的",
"iconPath": "static/tab/mine.png",
"selectedIconPath": "static/tab/mine-active.png"
}
]
},
"easycom": {
"autoscan": true,
"custom": {}
}
}
4. main.js 全局挂载
js
import Vue from 'vue'
import App from './App'
import store from './store'
import request from './utils/request'
Vue.prototype.$store = store
Vue.prototype.$api = request
const app = new Vue({
store,
...App
})
app.$mount()
5. store/index.js Vuex基础模板
js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
token: uni.getStorageSync('token') || '',
userInfo: {}
},
mutations: {
SET_TOKEN(state, val) {
state.token = val
uni.setStorageSync('token', val)
},
SET_USER(state, val) {
state.userInfo = val
}
},
actions: {},
getters: {}
})
6. App.vue 全局生命周期与样式
vue
<script>
export default {
onLaunch() {
console.log('应用启动')
},
onShow() {
console.log('进入前台')
},
onHide() {
console.log('切后台')
}
}
</script>
<style>
page {
background-color: #f6f6f6;
}
/* 全局公共样式 */
.flex-row {
display: flex;
flex-direction: row;
}
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
</style>
7. 页面跳转示例
js
// 普通页面传参
uni.navigateTo({
url: `/pages/detail/detail?id=${id}`
})
// 返回上一页
uni.navigateBack({ delta: 1 })
// 切换tab
uni.switchTab({
url: '/pages/index/index'
})
// 清空页面跳登录
uni.reLaunch({
url: '/pages/login/login'
})
8. 下拉刷新 + 触底分页 页面示例
vue
<template>
<view>列表数据</view>
</template>
<script>
export default {
data() {
return {
list: [],
page: 1,
limit: 10
}
},
onLoad() {
this.getList()
},
// 下拉刷新
onPullDownRefresh() {
this.page = 1
this.list = []
this.getList().finally(() => {
uni.stopPullDownRefresh()
})
},
// 触底加载
onReachBottom() {
this.page++
this.getList()
},
methods: {
async getList() {
const res = await this.$api({ url: '/list', data: { page: this.page, limit: this.limit } })
this.list = [...this.list, ...res.data]
}
}
}
</script>
夜雨聆风