文章
问答
冒泡
Taro微信小程序节点层级过深问题的解决方案

问题
在使用Taro开发小程序中使用自定义组件的时候,我们可能会遇到一个问题,莫名其妙的,无法获取到节点对象了。这种情况主要发生在操作节点的时候,可能在开发应用的时候不太会遇到,但是在组件库开发的时候,很难避免。

场景描述
以一个带时间的日历控件为例,默认在切换到时间选择的时候,我们会去获取下当前日历组件的高度,然后让时间模块保持同样的高度。在测试的时候,并没有发现问题,但是用在项目中的时候,高度坍塌了。因为没有获取到日历模块的节点高度。


日历部分


时间选择部分

通过开发工具查看Wxml结构,我们可以看到,在demo工程里,自定义组件的节点与其外部的节点是保持一致的。但是在业务系统中,自定义组件的节点被 #shadow-root 包裹了,并且id被加上了随机前缀,这就意味着我们无法再通过id获取节点对象了。


demo工程中的wxml


业务系统中的wxml

根据截图我们可以看到两者的区别,这就意味着导致问题的原因是shadow-root 造成的。这是小程序参考WebComponent 来实现dom隔离的,所以,直接用 createSelectorQuery 是获取不到节点的。

解决思路
按照微信官方文档的描述,这里需要将选择器的选取范围更改为自定义组件 component 内。根据这个思路,我们在Taro下找对应的解决方案。网上查找到的资料还是比较老的,使用this.$scope ,但是在当前版本中,该功能已经被废弃了。后来通过官方文档,找到了对应的解决方案。


根据文档提示,我们通过CustomWrapper 来解决这个问题。但是从CustomWrapper的介绍来看,似乎看不出来能解决这个问题。文档还是得看全才行。

我们对代码进行改造之后,效果已经正常了。

从Wxml结构可以看到加了一层 custom-wrapper。这里使用 ref 获取 CustomWrapper 实例,然后通过其 ctx 属性获取到 scope。
注意:在处理这种层级比较深的节点时,选择器不要用id,应该使用class,从wxml的截图可以看出,id会被带上随机前缀,所以是无法通过ID获取到的。


参考资料:
https://developers.weixin.qq.com/miniprogram/dev/api/wxml/SelectorQuery.html
https://docs.taro.zone/docs/ref#%E5%B5%8C%E5%A5%97%E5%B1%82%E7%BA%A7%E8%B6%85%E8%BF%87-baselevel-%E6%97%B6
https://docs.taro.zone/docs/components/viewContainer/custom-wrapper

taro

关于作者

落雁沙
非典型码农
获得点赞
文章被阅读