4.11 从欢迎页面跳转到文章页面
我们现在一共编写了两个页面:welcome欢迎页面与post文章页面。来尝试将两个页面连接起来,通过点击welcome页面的“开启小程序之旅”跳转到post文章页面。
首先将welcome页面重新调整为启动页面,代码如下:
调整启动页面的方法很简单,将启动页面的路径放在pages数组下的第一个元素即可。
4.11.1 事件
要从welcome页面跳转到post页面,需要使用事件来响应点击“开启小程序之旅”这个动作。
什么是事件?
严肃一些的定义是:事件是视图层(wxml)到逻辑层(js)的通信方式。简单一些理解,事件可以让我们在js里处理一些用户在界面上的一些操作并对这些操作做出反馈。比如点击welcome页面“开启小程序之旅”按钮后,需要在js里调用MINA框架的API,使页面从welcome跳转到post。
要实现这样的机制,需要做两件事情:
• 在组件上注册事件。注册事件将告诉小程序,我们要监听哪个组件的什么事件。在本例中,需要监听“开启小程序之旅”这个组件的tap事件。
• 在js中编写事件处理函数响应事件。也就是说,监听到事件后,需要编写自己的业务。在本例中,我们将调用MINA框架的导航API,让welcome页面跳转到post页面。
更改welcome.wxml页面的代码,如代码清单4-28所示。
和之前的代码相比并没有太大的改动,仅仅是在class="journey-container"的这个view组件上添加了一个catchtap="onTapJump"的事件绑定。事件绑定的写法同组件的写法相同。它的意思是,监听点击这个动作,当用户点击这个动作后,将执行一个onTapJump的函数,这个函数必须在页面的js中定义。下面的代码定义了tap事件的处理函数。
代码中为Page方法的Object参数定义了一个函数:onTapJump。函数的名称可以任意指定,但必须和代码清单4-28中定义的catchtap="onTapJump"保持一致。当用户点击或者触碰“开启小程序之旅”这个按钮后,MINA框架将执行onTapJump这个函数,并将一个event对象作为参数传递到函数里。
保存运行代码,点击“开启小程序之旅”,页面将从welcome欢迎页面跳转到post文章页面。
4.11.2 redirectTo与navigateTo
在上一小节中,我们在onTapJump函数里调用了wx.redirectTo方法从而实现了页面跳转。小程序共提供了3个导航API,以帮助开发者实现页面跳转。
• wx.redirectTo
• wx.navigateTo
• wx.switchTap(122100版本新增)
他们之间的区别是:redirectTo将关闭当前页面,跳转到指定页面;navigateTo将保留当前页面,跳转到指定页面;而switchTap只能用于跳转到带tabbar的页面,并关闭其他所有非tabBar页面。
switchTab页面将在后面学习tabbar选项卡时再具体介绍,本节主要来看看redirectTo和navigateTo的区别。
redirectTo和navigateTo在使用方式上完全相同,他们都接受一个Object对象作为参数。Object对象中最重要的属性是url,它将指定要跳转的页面路径。
请注意url是页面的路径,不要加上文件的扩展名(如同app.json中定义pages一样)。如果在页面路径后加上一个“.wxml”,比如将url设置为url: "../post/post.wxml",页面无法跳转,并会报错。
Object参数还可以接收3个方法,分别是:
• success 跳转页面成功时MINA框架将调用此函数。
• fail 跳转页面失败时MINA框架将调用此函数。
• complete 无论成功或者失败,MINA框架都将调用此函数。
具体写法可参考代码清单4-29。
将这3个方法拿出来单独列举是因为在小程序中,几乎所有异步类型的API都配备有这3个方法。比如后面要学习的操作反馈API:wx.showToast,获取用户信息API:wx.getUserInfo等。在以后的其他API学习过程中我们就不再一一列举这3个方法了。
再次保存并运行以上代码,点击跳转后,页面将跳转到post文章页面。此时我们发现没有办法再返回到welcome页面了。这就是redirectTo的特点,它将卸载welcome页面,并执行页面的onUnload事件函数。可以来验证一下,在welcome.js里加入一个onUnload函数和一个onHide函数。
运行代码,发现Console将输出“page is unload”,但并不会输出“page is hide”。
再来看看navigateTo。将代码清单4-29中的wx.redirectTo更改为wx.navigateTo。保存运行代码后将发现,navigateTo跳转到post页面后,页面左上角有一个返回按钮,如图4-23所示。点击返回后还可以再返回到welcome页面。除此之外,navigateTo将执行onHide事件回调,并输出了“page is hide”。
图4-23 左上角有【返回】按钮
所以,redirectTo将关闭当前页面并将页面卸载;而navigateTo仅仅会隐藏当前页面,还可以再次返回到被隐藏的页面。这是他们最重要的区别。
再来考虑一个问题。当navigateTo跳转到post页面后,再次从post页面返回到welcome页面时,post页面会执行onHide还是onUnload呢?答案是会执行post页面的onUnload函数(不能保证以后的版本是否还会更改,但目前的130400版本确实是会执行onUnload函数)。也就是说,当从子页面返回到父页面时,子页面会被卸载。开发者可以仿照welcome页面自行验证。
但事实上,子页面执行onUnload函数的行为是从122100版本后才更改的,在之前的版本中子页面返回到父页面并不会执行onUnload函数,造成大量的子页面残留在小程序中。这在当时给开发者带来了巨大的困扰,还好官方在后续版本中更改了这个行为。页面是否被卸载是非常重要的行为,不卸载页面将使全局性的一些行为,比如音乐播放的处理,变得非常复杂。所以,了解这些页面的生命周期对于开发者来说是很重要的,否则极易引起bug。
我们还可以再试试wx.switchTab这个方法,将welcome.js中的wx.navigateTo更改为wx.switchTab,其他保持不变,运行一下代码。
页面无法执行跳转,且Console将输出jump failed。原因之前我们解释过,switchTab只能跳转到带有tabbar选项卡的页面,而post页面并不带有选项卡,所以无法执行跳转。tabbar的配置将在后面讲到,现在开发者无须关心。
现在,我们暂时选取navigateTo作为跳转方法。
4.11.3 小程序最多只能有5层页面
当我们使用navigateTo从父页面跳转到子页面后,就形成了2个页面层级。可以继续在子页面里使用navigateTo跳转到子页面。
但小程序里强制规定,只允许有最多五层父子页面。所以请开发者注意,尽量避免多层级的交互方式。事实上,太多的子页面将严重影响用户的产品体验。建议页面最多不要超过3层。
redirectTo不存在这个问题,因为当跳转到另一个页面后,上一个页面被强制卸载掉了。
4.11.4 冒泡事件与非冒泡事件
什么是冒泡事件?
冒泡事件指某个组件上的时间被触发后,事件还会向父级元素传递;父级元素还会继续向父级的父级传递,一直到页面的顶级元素。而非冒泡事件则不会向父级元素传递事件。
在4.11.1小节中,我们使用了tap事件,监听点击或者触摸动作,而tap是一个冒泡事件。常见的冒泡事件类型还有下面几种:
• touchstart 手指触摸动作开始。
• touchmove 手指触摸后移动。
• touchcancel 手指触摸动作被打断,如来电提醒、弹窗。
• touchend 手指触摸动作结束。
• tap 手指触摸后马上离开。
• longtap 手指触摸后,超过350ms再离开。
相对于PC上的Web浏览器,小程序的事件并不多。需要注意的是,在wxml组件里注册事件时,不可以直接使用tap="function"或touchmove="function",需要在事件名之前添加catch或者bind前缀。比如在welcome页面跳转时,我们就使用了catchtap而并没有直接使用tap。
bind和catch有什么区别?
区别在于,对于以上几个冒泡事件,catch将阻止事件继续向父节点传播,而bind不会阻止事件的传播。
基本上所有的组件都有以上这些冒泡事件。
除以上6种事件外,如无特殊申明都是非冒泡事件,非冒泡事件大多不是通用事件,而是某些组件特有的事件。如<form/>的submit事件,<input/>的input事件,<scroll-view/>的scroll事件等。