Taro开发微信小程序插件踩坑记录

892 阅读4分钟

最近做项目时,需要开发一个功能给小程序用,由于功能比较独立,稍加考虑便决定采用小程序插件的方式嵌入,之前组内开发小程序一直使用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方法,

使用这种方式写完之后,发现系统默认的分享给好友按钮已经是点亮状态,点击按钮手动触发分享,不出意外,分享的标题也是刚刚设置的,问题解决~