不止一页:页面路由与导航
不止一页:页面路由与导航
所属专栏:《微信小程序-实战笔记30讲》
作者:码力无边
前言
我们已经学会了如何在一个页面内构建丰富的UI和复杂的交互。但这就像我们精心装修好了一个房间。一个完整的“家”,需要有客厅、卧室、厨房等多个房间,并且需要有门和走廊将它们连接起来。
在小程序中,这些“房间”就是我们之前在app.json
中定义的各个页面,而连接它们的“门和走廊”,就是我们今天要学习的页面路由与导航机制。
小程序管理所有页面的行为,就像管理一个页面栈。你可以把它想象成一摞盘子:
- 打开一个新页面,就像往这摞盘子顶部放上一个新盘子。
- 返回上一个页面,就像从顶部拿走一个盘子。
今天,我们将学习小程序提供的导航API,掌握如何自如地在各个页面间“穿梭”,并学习如何在穿梭的过程中,携带重要的“行李”——页面参数。
一、小程序页面栈的奥秘
在深入API之前,理解页面栈的概念至关重要。小程序框架会维护一个页面栈,记录了所有被打开过的页面路径。
假设我们有A、B、C、D四个页面,A是首页。
- 启动小程序:进入首页A。页面栈:
[A]
- 从A跳转到B:页面栈:
[A, B]
(B在A的上面) - 从B跳转到C:页面栈:
[A, B, C]
(C在B的上面) - 从C返回:C被销毁,回到B。页面栈:
[A, B]
- 从B再跳转到D:页面栈:
[A, B, D]
(D在B的上面)
这个栈的层级最多不能超过10层。所以,要避免设计出无限 deep link 的页面跳转逻辑。
可以通过 getCurrentPages()
函数在任何页面的JS中获取当前的页面栈实例,它返回一个数组,数组的最后一个元素就是当前页面。
// 在任何页面的js里
const pages = getCurrentPages();
console.log(pages); // 打印出页面栈
const currentPage = pages[pages.length - 1]; // 获取当前页面实例
console.log(currentPage.route); // 打印当前页面的路径
二、四种核心路由方式:各司其职
小程序提供了四种主要的API来实现页面跳转,它们分别对应不同的业务场景。
1. wx.navigateTo(Object object)
:保留当前,开启新篇
这是最常用的跳转方式,它会保留当前页面,跳转到应用内的某个非tabBar
页面。
- 行为:将新页面压入页面栈。
- 返回:用户点击左上角的返回按钮或调用
wx.navigateBack
可以返回到原页面。 - 场景:从列表页进入详情页,完成某个操作后还希望返回列表。
示例:
// 从列表页跳转到详情页
wx.navigateTo({url: '/pages/detail/detail',success: function(res) {// 跳转成功后的回调},fail: function(err) {// 跳转失败后的回调}
})
2. wx.redirectTo(Object object)
:关闭当前,翻开新页
这种方式会关闭当前页面,跳转到应用内的某个非tabBar
页面。
- 行为:将当前页面出栈,然后将新页面压入页面栈。
- 返回:左上角没有返回按钮,因为前一页已经被销毁了。
- 场景:从注册页跳转到首页。用户注册成功后,我们不希望他能再返回到注册页。
示例:
// 从注册页跳转到首页
wx.redirectTo({url: '/pages/index/index'
})
3. wx.switchTab(Object object)
:切换“频道”
专门用于跳转到tabBar
页面,并会关闭所有非tabBar
页面。
- 行为:清空页面栈,只保留目标
tabBar
页面作为栈底。 - 场景:从任何一个普通页面,点击底部导航栏回到首页、个人中心等核心页面。
示例:
// 跳转到“我的”tab页
wx.switchTab({url: '/pages/profile/profile'
})
注意:
wx.navigateTo
和wx.redirectTo
不能用于跳转到tabBar
页面,否则会报错。
4. wx.navigateBack(Object object)
:返回上一“站”
关闭当前页面,返回上一页面或多级页面。
- 行为:将一个或多个页面出栈。
- 参数:可以通过
delta
参数决定返回的层数,默认为1。
示例:
// 仅返回上一页
wx.navigateBack();// 返回上两页
wx.navigateBack({delta: 2
});
三、页面间如何传递参数?
在页面跳转时,我们常常需要把一些信息从当前页传递到目标页,比如商品ID、文章ID等。
1. 在URL中拼接参数 (最常用)
这是最简单直接的方式。在跳转的url
中,像网页的GET请求一样,使用?
拼接参数,多个参数用&
隔开。
发送方 (pages/list/list.js):
const productId = 'p001';
const from = 'homepage';wx.navigateTo({url: `/pages/detail/detail?id=${productId}&from=${from}`
})
接收方 (pages/detail/detail.js):
在目标页面的onLoad
生命周期函数中,可以通过参数options
对象来接收。
Page({onLoad: function (options) {console.log('接收到的参数是:', options); // 输出: { id: 'p001', from: 'homepage' }const productId = options.id;const from = options.from;// 接下来就可以用这些参数去请求商品详情数据了}
})
2. EventChannel:页面间的“专属信使” (高级用法)
对于一些复杂的、非字符串的数据(如对象、函数),通过URL传递会很麻烦。这时,EventChannel
提供了一种更强大、更灵活的通信方式。
它允许跳转源页面向目标页面传递一个事件通道,双方可以通过这个通道进行双向通信。
发送方 (A页面):
wx.navigateTo({url: '/pages/b/b',success: function(res) {// 通过 eventChannel 向被打开页面传送数据res.eventChannel.emit('acceptDataFromOpenerPage', { data: { name: '码力无边', level: 99 } })}
})
接收方 (B页面):
在onLoad
中监听事件。
Page({onLoad: function (options) {const eventChannel = this.getOpenerEventChannel();// 监听 acceptDataFromOpenerPage 事件,获取上一页面通过 eventChannel 传送到当前页面的数据eventChannel.on('acceptDataFromOpenerPage', function(res) {console.log('收到了来自A页面的复杂数据:', res.data);})}
})
EventChannel还能实现B页面向A页面回传数据,功能非常强大,适用于复杂的页面间协作场景。
结语
今天,我们打通了小程序内部的“交通网络”,学会了如何在多个页面之间自如地穿行。我们掌握了:
- 页面栈的概念,它是小程序路由管理的基础。
- 四种核心导航API:
navigateTo
(进入),redirectTo
(替换),switchTab
(切换),navigateBack
(返回),以及它们各自的适用场景。 - 两种页面间通信方式:通过 URL 拼接参数 传递简单数据,以及通过 EventChannel 传递复杂数据。
现在,你已经有能力将之前学习的单页面开发技巧串联起来,构建出一个具有完整流程和多页面结构的应用程序了。
我们的应用已经可以在内部自由流转了,但它仍然是一个“信息孤岛”。如何与外部世界——也就是我们的服务器——进行通信,获取真实的数据呢?下一讲,我们将学习网络请求wx.request
,为你的小程序装上连接世界的“天线”。
我们下篇见!