最近做项目时,需要开发一个功能给小程序用,由于功能比较独立,稍加考虑便决定采用小程序插件的方式嵌入,之前组内开发小程序一直使用Taro,便定下了用Taro开发插件的基础架构,也开始了本次踩坑之旅......
问题一: 公共组件样式丢失!?
业务开发中,难以避免多个页面有同样效果的组件,封装了一个项目内通用的按钮组件,自己使用时没有任何问题,等到别的同事在其他页面也开始引用时,才发现出现了问题,竟然在两个页面的样式都丢失了,起初以为是组件样式写的有问题,经过多从调整仍然无法正常展示,后来在其中一个页面取消组件的引用,发现另一个页面的样式也回归正常了,到这里基本上确定了是组件被多次引用而导致的问题。查看打包文件发现是因为taro编译的时候,如果有样式被多次引用,会自动把这段样式提取到公共样式common.wxss中, 但此问题出现的原因恰恰是这段打包优化。
同时打开页面的打包文件可以发现,样式只是被提取到了common.wxss中,但是并没有在页面中进行引用
这也就导致了组件的样式丢失。发现问题根源之后,解决问题就变得很简单了,最初的方案是每次编译之后手动把每个页面的common.wxss的引入加上,方法虽然很有效,但操作起来实在太麻烦了,毕竟页面太多,每个页面的层级不一样,繁琐而易失误。
由于是编译时出现的错误,便考虑在编译阶段解决,Taro把公共样式引入丢了,那就再手动加回去~,Taro打包使用的是webpack,于是可以从webpack插件入手: 参考代码如下
const { ConcatSource } = require('webpack-sources')
const Regexp = /(?<=plugin/(components|pages))/.+.wxss/g
class WxssImportPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync(
'WxssImportPlugin',
(compilation, callback) => {
for (let [name, assets] of Object.entries(compilation.assets)) {
if (Regexp.test(name)) {
const times = name.split('/').length - 2;
const firstLine = `@import '${Array(times).fill('../').join('') + 'common.wxss'}';\r\n`
compilation.assets[name] = new ConcatSource(firstLine + assets.source())
}
}
callback()
}
);
}
}
module.exports = WxssImportPlugin
主要思想就是在打包时,找到pages目录下的所有wxss文件,根据路径深度计算其引用common.wxss的相对路径,补充到文件第一行,至此,问题解决。
问题二: useReachBottom、usePageScroll 无法监听页面滚动事件!!??
部分页面有懒加载的功能,以往做懒加载时都是通过监听页面滚到到底部来实现,这次也不例外。但当开始调试时出现了问题,无论页面怎么滚动,useReachBottom设置的回调函数都不执行,换了真机调试和微信开发者工具都不生效,决定换一个钩子函数,使用usePageScroll来监听页面滚动,自己计算是否滚动到底部。但是尝试之后发现,所有与页面滚动相关的事件在小程序插件环境中都不触发。
由于懒加载功能不能不做,只能找寻替代方案,原生小程序中,提供的有scroll-view组件,其中可以通过bindscroll和bindscrolltolower两个事件接收滚动事件,经过尝试后发现该组件可以暴露出滚动事件,将原本的监听页面滚动的逻辑改为监听元素的滚动,问题解决,参考代码如下:
需要注意的是: 使用ScrollView时,需要设置高度和滚动方向。
问题三: useRouter 无法获取路由参数!!!???
这个问题比较诡异,其实useRouter是能拿到路由参数的,在页面初始化时,直接取useRouter返回值取赋值给state都无法成功,console打印出来的值却是正常的。通过debugger发现,在执行到取值时,useRouter返回的事undefined
由于useRouter hooks本质上是Taro.getCurrentInstance().router, hooks写法没法在初始化时取到值,且无法将useRouter写到类似useDIdShow等钩子中,便在使用时通过Taro.getCurrentInstance().router的方式取到router对象,问题解决
问题四: useShareTimeline useShareAppMessage 两个用于分享页面的Hooks失效!!!!????
该问题的现象是,在页面中已经写了useShareMessage和useShareTimeline方法, 但是系统默认的分享按钮一直是置灰状态,手动触发分享时,设置的分享标题也没有生效。与上述三个问题相比,这个问题是最让我绝望的,分享功能在本项目中非常重要,一旦没法实现就意外着需要重新做了,再加上尝试各种方案都无法解决,一度濒临无解。
由于之前已经解决了ueRouter useReachBottom等hook失效的问题,突然想到有没有可能是Taro对react的hooks版本兼容性不好导致的,于是新建了一个页面,采用class componens的方式,在class写法中,可以直接在class组件对象中写onShareAppMessage方法,
使用这种方式写完之后,发现系统默认的分享给好友按钮已经是点亮状态,点击按钮手动触发分享,不出意外,分享的标题也是刚刚设置的,问题解决~