Appearance
实战篇 9-微信小程序开发填坑指南
微信小程序开发填坑指南
众所周知,小程序开发是有诸多限制的,所以必然少不了会遇到很多坑,下面就说一说我们在开发时候遇到的一些问题,并给与解决方法与建议。
页面栈只有 10 层
估计是每个页面的数据在小程序内部都有缓存,所以做了 10 层的限制。带来的问题就是假如页面存在循环跳转,即 A 页面可以跳到 B 页面,B 页面也可以跳到 A 页面,然后用户从 A 进入了 B,想返回 A 的时候,往往是直接在 B 页面里点击跳转到 A,而不是点返回到 A,如此一来,10 层很快就突破了。
所以我们自己对 navigateTo
函数做了一层封装,防止溢出。
// 处理微信跳转超过10层
function jumpUrl (url, options = {} ) {
const pages = Taro.getCurrentPages()
let method = options.method || 'navigateTo'
if (url && typeof url === 'string') {
if (method === 'navigateTo' && pages.length >= PAGE_LEVEL_LIMIT - 3) {
method = 'redirectTo'
}
if (method === 'navigateToByForce') {
method = 'navigateTo'
}
if (method === 'navigateTo' && pages.length == PAGE_LEVEL_LIMIT) {
method = 'redirectTo'
}
Taro[method]({
url
})
}
}
可以看到,代码很简单,先是判断当前页面的栈数,超过了限定值后,就改为使用redirectTo
方法,防止页面栈溢出导致错误。
页面内容有缓存
上面说到,页面内容有缓存。所以假如某个页面是根据不同的数据渲染视图,新渲染时会有上一次渲染的缓存,导致页面看起来有个闪烁的变化,用户体验非常不好。其实解决的办法也很简单,每次在onHide
生命周期中清理一下当前页面的数据就好了。
页面不会自动刷新
怎样理解这句话?常见的有两种情况:
- A 页面 —> B 页面,B 页面返回 A 页面时,A 页面不会自动刷新
- 底部的 TabBar,切换时,页面也不会自动刷新
这会导致什么情况呢?例如购物车页面是在底部的 TabBar 里的,假如笔者在别的页面将某个商品加入购物车,点回来的时候并不会刷新,这就和需求很不符合、体验也不友好。解决的办法很简单,每次都在页面的 onShow
生命周期里触发拉数据的逻辑,而不是在 onLoad
、onReady
等生命周期去做这个事情。
小程序说到底不是 H5,不会说每次进入页面就会刷新,也不会离开就销毁,刷新、清理数据的动作都需要自己在生命周期函数里主动触发。
不能随时地监听页面滚动事件
页面的滚动事件只能通过 onPageScroll
来监听,所以当笔者想在组件里进监听操作时,要将该部分的逻辑提前到 onPageScroll
函数,提高了抽象成本。例如笔者需要开发一个滚动到某个位置就吸顶的 tab
,本来可以在 tab
内部处理的逻辑就被提前了,减少了其可复用性。这个是小程序本身的设计缺陷,似乎没有什么很好的解决办法。
小程序与 WebView 之间不能随意通信
小程序不支持本地存储,抑或是接口之类的让两者可以随意通信,只有 bindmessage
属性允许两者在特定情况下获取到 H5 传过来的信息。或者你也可以选择在 URL
里携带信息。
之前遇到的一个情况就是 H5 里的某个请求需要携带上登录后的 token
信息,而这个登录逻辑是在小程序里的,因而 token
储存在了小程序的 storage
里,无法在 H5 里获取。经过了一番挣扎后,最终还是通过 URL
把 token
信息带到了 H5,实现了在 WebView 里的登陆态传递。
decodeURIComponent
decodeURIComponent
在访问时不仅能生成小程序所携带的参数,也可以分享页面携带的参数。官方文档的例子:
// 这是首页的 js
Page({
onLoad: function(options) {
// options 中的 scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene
var scene = decodeURIComponent(options.scene)
}
})
之前写某个页面的时候,忘记了 decodeURIComponent
,导致投放广告时,没有获得正确的参数。最后排查的结果是没有 decodeURIComponent
这个参数,又重新发了一版后,才完美解决这个问题。
某些组件总是会在最上层
像 map
、canvas
、video
、textarea
等是由客户端创建的原生组件,原生组件的层级是最高的,并不能通过设置 z-index
来更改元素层级。之前有个需求是使用 canvas
来绘制一些东西,绘制完后需要弹出一个浮层,然后 canvas
直接把浮层挡住了。
解决的办法是使用官方提供的 cover-view
组件来包裹浮层,但体验并不好。
有弹出层时,难以禁止底部页面滚动
有弹出层时,我们希望可以把底部页面的滚动给禁止掉,这个在 H5 可以用 position:fixed
定位加滚动指定高度实现。而在小程序中,这样做会有一个延迟,页面先是会回到顶部,然后再跳到指定的地方,观感非常差。而如果是直接用 catchtouchmove='preventTouchMove'
来阻止滑动事件冒泡,那会导致弹出层里面的滚动效果给禁掉,也是行不通的。
最后的办法是在最外层使用 scroll-view
组件包裹,然后有弹出层时,将 scroll-y
属性设置为 false
从而禁止页面滚动。
Taro 开发需要注意的地方
Taro 在我们部门的几个核心开发者的努力下,经过多个版本的迭代,已经开发出 ESLint 插件,及补充完整了 Taro 文档。大家只要遵循 ESLint 插件规范,查看文档,不会有太大问题,有问题欢迎提 Issue。