Skip to content

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 中定义触发距离 onReachBottomDistance
  • onPageScroll 里不要写交互复杂的 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 跳转。

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 对象实例
// #endif
const 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()
}