UniApp 页面与路由
页面简介
在 uni-app 中,一个页面就是一个符合 Vue SFC 规范的 .vue 文件或 .nvue 文件。.vue 页面使用 webview 渲染,.nvue 页面使用原生渲染。
每次新建页面,均需在 pages.json 中配置 pages 列表。未配置的页面在编译阶段会被忽略。
应用生命周期
仅在 App.vue 中监听:
| 函数名 | 说明 |
|---|---|
| onLaunch | 初始化完成时触发(全局只触发一次) |
| onShow | 启动或从后台进入前台 |
| onHide | 从前台进入后台 |
| onError | 报错时触发 |
| onUniNViewMessage | 对 nvue 页面发送的数据进行监听 |
| onUnhandledRejection | 未处理的 Promise 拒绝事件 |
| onPageNotFound | 页面不存在 |
| onThemeChange | 系统主题变化 |
页面生命周期
| 函数名 | 说明 |
|---|---|
| onInit | 监听页面初始化,早于 onLoad |
| onLoad | 监听页面加载,参数为上个页面传递的数据 |
| onShow | 监听页面显示,每次出现在屏幕都触发 |
| onReady | 监听页面初次渲染完成 |
| onHide | 监听页面隐藏 |
| onUnload | 监听页面卸载 |
| onResize | 监听窗口尺寸变化 |
| onPullDownRefresh | 监听下拉动作 |
| onReachBottom | 页面滚动到底部 |
| onTabItemTap | 点击 tab 时触发 |
| onShareAppMessage | 用户点击右上角分享 |
| onPageScroll | 监听页面滚动 |
| onNavigationBarButtonTap | 监听原生标题栏按钮点击 |
| onBackPress | 监听页面返回 |
| onNavigationBarSearchInputChanged | 监听搜索输入框内容变化 |
| onNavigationBarSearchInputConfirmed | 监听搜索按钮点击 |
| onNavigationBarSearchInputClicked | 监听搜索框点击 |
| onShareTimeline | 转发到朋友圈 |
| onAddToFavorites | 收藏 |
注意:
onInit仅百度小程序基础库 3.260 以上支持onReachBottom可在 pages.json 中定义触发距离onReachBottomDistanceonPageScroll里不要写交互复杂的 js,非 h5 端逻辑层和渲染层通信有损耗onBackPress上不可使用 async,会导致无法阻止默认返回- nvue 页面 weex 编译模式支持的生命周期同 weex
组件生命周期
与 Vue 标准组件生命周期相同:
| 函数名 | 说明 |
|---|---|
| beforeCreate | 实例初始化之前 |
| created | 实例创建完成后 |
| beforeMount | 挂载开始之前 |
| mounted | 挂载到实例之后 |
| beforeUpdate | 数据更新时(仅 H5 支持) |
| updated | 数据更改后(仅 H5 支持) |
| beforeDestroy | 实例销毁之前 |
| destroyed | 实例销毁后 |
页面通信(uni.$emit / uni.$on / uni.$once / uni.$off)
全局级别事件,跨任意组件、页面、nvue、vue。
uni.$emit(eventName, OBJECT)
触发全局自定义事件:
js
uni.$emit('update', { msg: '页面更新' })uni.$emit('update', { msg: '页面更新' })uni.$on(eventName, callback)
监听全局自定义事件:
js
uni.$on('update', function (data) {
console.log(data.msg)
})uni.$on('update', function (data) {
console.log(data.msg)
})uni.$once(eventName, callback)
监听一次,触发后移除:
js
uni.$once('update', function (data) {
console.log(data.msg)
})uni.$once('update', function (data) {
console.log(data.msg)
})uni.$off([eventName, callback])
移除监听器:
- 无参数:移除所有事件监听器
- 只提供事件名:移除该事件所有监听器
- 提供事件与回调:只移除该回调
使用场景示例:
vue
<!-- 登录页触发 -->
uni.$emit('login', { token: 'user123456', nickName: 'wk123' })
<!-- 用户中心页监听 -->
onLoad() { uni.$on('login', (uinfo) => { this.usnerInfo = uinfo }) }
onUnload() { uni.$off('login') }<!-- 登录页触发 -->
uni.$emit('login', { token: 'user123456', nickName: 'wk123' })
<!-- 用户中心页监听 -->
onLoad() { uni.$on('login', (uinfo) => { this.usnerInfo = uinfo }) }
onUnload() { uni.$off('login') }路由
uni-app 页面路由由框架统一管理,在 pages.json 中配置。支持两种跳转方式:navigator 组件和 API 跳转。
navigator 组件
html
<navigator url="navigate/navigate?title=navigate" hover-class="navigator-hover">
<button type="default">跳转到新页面</button>
</navigator>
<navigator url="redirect/redirect?title=redirect" open-type="redirect">
<button type="default">在当前页打开</button>
</navigator>
<navigator url="/pages/tabBar/extUI/extUI" open-type="switchTab">
<button type="default">跳转tab页面</button>
</navigator><navigator url="navigate/navigate?title=navigate" hover-class="navigator-hover">
<button type="default">跳转到新页面</button>
</navigator>
<navigator url="redirect/redirect?title=redirect" open-type="redirect">
<button type="default">在当前页打开</button>
</navigator>
<navigator url="/pages/tabBar/extUI/extUI" open-type="switchTab">
<button type="default">跳转tab页面</button>
</navigator>API 跳转
js
// 跳转新页面并传参
uni.navigateTo({ url: 'test?id=1&name=uniapp' })
// 接收参数
export default { onLoad: function (option) { console.log(option.id) } }// 跳转新页面并传参
uni.navigateTo({ url: 'test?id=1&name=uniapp' })
// 接收参数
export default { onLoad: function (option) { console.log(option.id) } }页面栈
| 路由方式 | 页面栈表现 |
|---|---|
| 初始化 | 新页面入栈 |
| 打开新页面 | 新页面入栈 |
| 页面重定向 | 当前页出栈,新页面入栈 |
| 页面返回 | 页面不断出栈 |
| Tab 切换 | 页面全部出栈,只留新 Tab 页面 |
| 重加载 | 页面全部出栈,只留新页面 |
路由规则
navigateTo,redirectTo— 只能打开非 tabBar 页面switchTab— 只能打开 tabBar 页面reLaunch— 可以打开任意页面- 不能在
App.vue里进行页面跳转
getCurrentPages()
获取当前页面栈实例,数组形式,第一个为首页,最后一个为当前页面。
js
const pages = getCurrentPages()
const page = pages[pages.length - 1]
// #ifdef APP-PLUS
const webview = page.$getAppWebview() // 获取 webview 对象实例
// #endifconst pages = getCurrentPages()
const page = pages[pages.length - 1]
// #ifdef APP-PLUS
const webview = page.$getAppWebview() // 获取 webview 对象实例
// #endif下拉刷新
在 pages.json 中开启:
json
{
"path": "pages/pull_down/index",
"style": {
"enablePullDownRefresh": true
}
}{
"path": "pages/pull_down/index",
"style": {
"enablePullDownRefresh": true
}
}js
onPullDownRefresh() {
console.log('refresh')
setTimeout(() => uni.stopPullDownRefresh(), 1000)
}
// 主动触发
uni.startPullDownRefresh()onPullDownRefresh() {
console.log('refresh')
setTimeout(() => uni.stopPullDownRefresh(), 1000)
}
// 主动触发
uni.startPullDownRefresh()自定义导航头
在 pages.json 中设置 navigationStyle: "custom" 或 titleNView: false 去掉原生导航栏:
json
{
"globalStyle": {
"navigationStyle": "custom"
}
}{
"globalStyle": {
"navigationStyle": "custom"
}
}状态栏占位方案:
CSS 方式:
vue
<view class="status_bar"></view>
<style>
.status_bar { height: var(--status-bar-height); width: 100%; }
</style><view class="status_bar"></view>
<style>
.status_bar { height: var(--status-bar-height); width: 100%; }
</style>JS 方式:
js
onLoad() {
this.statusHeight = plus.navigator.getStatusbarHeight()
}onLoad() {
this.statusHeight = plus.navigator.getStatusbarHeight()
}
Cao Note