在开发小程序的时候,会碰到页面间进行跳转的需求,小程序间页面跳转的方法有很多,大体分为两类,一个是指令方式,一个是用过js控制。
一、js控制跳转
1、wx.navigateTo
wx.navigateTo用于保留当前页面、跳转到应用内的某个页面,使用 wx.navigateBack可以返回到原页面。对于页面不是特别多的小程序,通常推荐使用 wx.navigateTo进行跳转, 以便返回原页面,以提高加载速度。当页面特别多时,则不推荐使用。
// 保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面。
// 注意:调用 navigateTo 跳转时,调用该方法的页面会被加入堆栈,但是 redirectTo
wx.navigateTo({
url: 'page/home/home?user_id=111'
})
2、wx.navigateBack
wx.navigateBack用于关闭当前页面,并返回上一页面或多级页面。开发者可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。这个 API 需要填写的参数只有 delta,表示要返回的页面数。若 delta 的取值大于现有可返回页面数时,则返回到用户进入小程序的第一个页面。当不填写 delta 的值时,就默认其为 1(注意,默认并非取 0),即返回上一页面
// 关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。
wx.navigateTo({
url: 'page/home/home?user_id=111' // 页面 A
})
wx.navigateTo({
url: 'page/detail/detail?product_id=222' // 页面 B
})
// 跳转到页面 A
wx.navigateBack({
delta: 2
})
3、wx.redirectTo
wx.redirectTo当页面过多时,被保留页面会挤占微信分配给小程序的内存,或是达到微信所限制的 5 层页面栈。这时,我们应该考虑选择 wx.redirectTo。wx.redirectTo()用于关闭当前页面,跳转到应用内的某个页面。这样的跳转,可以避免跳转前页面占据运行内存,但返回时页面需要重新加载,增加了返回页面的显示时间。
// 关闭当前页面,跳转到应用内的某个页面。
wx.redirectTo({
url: 'page/home/home?user_id=111'
})
4、wx.switchTab
tabBar页面专用,对于跳转到 tab bar 的页面,最好选择 wx.switchTab(),它会先关闭所有非 tab bar 的页面。其次,也可以选择 wx.reLaunch(),它也能实现从非 tab bar 跳转到 tab bar,或在 tab bar 间跳转,效果等同 wx.switchTab()。使用其他跳转 API 来跳转到 tab bar,则会跳转失败。
// 跳转到tabBar页面(在app.json中注册过的tabBar页面),同时关闭其他非tabBar页面。
wx.switchTab({
url: 'page/index/index'
})
5、wx.reLaunch
wx.reLaunch()与 wx.redirectTo()的用途基本相同, 只是 wx.reLaunch()先关闭了内存中所有保留的页面,再跳转到目标页面。
// 关闭所有页面,打开到应用内的某个页面。
wx.reLanch({
url: 'page/home/home?user_id=111'
})
二、指令式跳转
// navigator 组件默认的 open-type 为 navigate
<navigator url="/page/navigate/navigate?title=navigate" hover-class="navigator-hover">跳转到新页面</navigator>
// redirect 对应 API 中的 wx.redirect 方法
<navigator url="../../redirect/redirect/redirect?title=redirect" open-type="redirect" hover-class="other-navigator-hover">在当前页打开</navigator>
// switchTab 对应 API 中的 wx.switchTab 方法
<navigator url="/page/index/index" open-type="switchTab" hover-class="other-navigator-hover">切换 Tab</navigator>
// reLanch 对应 API 中的 wx.reLanch 方法
<navigator url="../../redirect/redirect/redirect?title=redirect" open-type="redirect" hover-class="other-navigator-hover">关闭所有页面,打开到应用内的某个页面</navigator>
// navigateBack 对应 API 中的 wx.navigateBack 方法
<navigator url="/page/index/index" open-type="navigateBack" hover-class="other-navigator-hover">关闭当前页面,返回上一级页面或多级页面</navigator>
navigator的open-type属性 可选值 'navigate'、'redirect'、'switchTab',对应于wx.navigateTo、wx.redirectTo、wx.switchTab的功能:
open-type="navigate"等价于API的 wx.navigateTo
而wx.navigateTo的url是需要跳转的应用内非 tabBar 的页面的路径
open-type="redirect"等价于API的 wx.redirectTo 而wx.redirectTo的url是需要跳转的应用内非 tabBar 的页面的路径 open-type="switchTab"等价于API的
wx.switchTab而wx.switchTab的url是需要跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
三、页面通信
1、使用url 路径传递
1.1、传递普通字符串
通过在url后面拼接参数,参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔;如 ‘path?key=value&key2=value2’。
// A页面跳转代码
goB(){
wx.navigateTo({
url: '/pages/B/index?id=value',
})
},
// B页面接收代码
onLoad: function (options) {
console.log('id', options.id)
}
1.2、传递对象
上面的案例是字符串参数,但是很多情况下需要传递对象。这个时候需要先把对象通过JSON.stringify(obj)将 object 对象转换为 JSON 字符串进行参数传递,再到接收页面通过JSON.parse解析使用。
// A页面跳转代码
goB(){
let userStr = JSON.stringify(this.data.userInfo)
wx.navigateTo({
url: '/pages/B/index?id='+userStr,
})
}
// B页面接收代码
onLoad: function (options) {
console.log('id', JSON.parse(options.id))
}
2、使用globalData 全局变量
globalData是小程序app.js中固定的一个属性,存储的数据可在全项目任意处使用
// app.js
App({
globalData:{},
})
// aaa.js
const app = getApp();
app.globalData.name='xiaowang';
// bbb.js
const app = getApp();
console.log(app.globalData.name) //xiaowang
3、使用storage 数据缓存
storage是微信分给每个小程序的缓存,单个参数最大1M,数据总和最大10M
// aaa.js
Page({
data:{
name:'xiaowang'
},
})
//只支持原生类型、Date、及能够通过JSON.stringify序列化的对象
wx.setStorageSync('name',this.data.name)
// bbb.js
console.log(wx.getStorageSync(name)) //xiaowang
4、事件通信
通过事件通信通道
// A页面跳转代码
goB() {
wx.navigateTo({
url: '/pages/B/index',
success:(res)=>{
// 发送一个事件
res.eventChannel.emit('toB',{ userInfo: this.data.userInfo })
}
})
}
// B页面接收代码
onLoad: function (options) {
// 获取所有打开的EventChannel事件
const eventChannel = this.getOpenerEventChannel();
// 监听 index页面定义的 toB 事件
eventChannel.on('toB', (res) => {
console.log(res.userInfo)
})
}
在A-B-C多个页面直接建立数据通道
//注意this.getOpenerEventChannel() 只能在navigateTo模板页面使用,其他更多页面使用时,
//可以保存在getApp()全局实例中以备其他页面使用
// 保留AB通道事件,已备C页面给A页面发送数据
// B页面
const eventChannel = this.getOpenerEventChannel()
getApp().pageBEventChannel = eventChannel
//C页面
getApp().pageBEventChannel.emit('PageAacceptDataFromPageC', { data: 'Page C->A' });
5、使用第三方iny bus 事件
5.1、安装
方式一. 通过 npm 安装
# npm
npm i iny-bus -save
# yarn
yarn add iny-bus --production
方式二. 下载代码
直接通过 git 下载 iny-bus 源代码,并将dist目录 中的 index.js 拷贝到自己的项目中
git clone https://github.com/landluck/iny-bus.git
5.2、使用
使用内置方法
// App、Page、Component 使用方法一致
import bus from 'iny-bus'
// bus.app bus.page bus.component
const page = bus.page({
busEvents: {
// 简单使用
postMessage(msg) {
this.setData({
msg
})
},
// 一次性事件
postMessageOnce: {
handler (msg) {
this.setData({
msg
})
},
once: true
}
},
onLoad() {
bus.emit('postMessage', 'hello bus')
bus.emit('postMessageOnce', 'hello bus once')
}
})
Page(page)
在生命周期中使用
// 小程序
import bus from 'iny-bus'
// 添加事件监听
// 在 onLoad 中注册, 避免在 onShow 中使用
onLoad () {
this.eventId = bus.on('事件名', (a, b, c, d) => {
// 支持多参数
console.log(a, b, c, d)
this.setData({
a,
b,
c
}
})
}
// 移除事件监听,该函数有两个参数,第二个事件id不传,会移除整个事件监听,传入ID,会移除该页面的事件监听,避免多余资源浪费, 在添加事件监听后,页面卸载(onUnload)时建议移除
onUnload () {
bus.remove('事件名', this.eventId)
}
// 派发事件,触发事件监听处更新视图
// 支持多参传递
onClick () {
bus.emit('事件名', a, b, c)
}
// 清空所有事件监听
onClear () {
bus.clear()
}