Taro 获取小程序组件实例

633 阅读3分钟

为什么要获取组件实例

Taro中,部分与wxml相关的api,如:Taro.createSelectorQueryTaro.createIntersectionObserver,在自定义组件(小程序组件)中使用时,需要使用this.createSelectorQuery来代替。但是在Function组件中,是无法直接获取到当前自定义组件的this实例的。

大部分情况下,在我们的React组件中直接使用Taro.createSelectorQuery这种api是没有问题的,因为taro在编译时,并没有把我们的组件直接作为小程序原生组件来渲染,还是直接在主页面中进行渲染的。

如下:

<!--页面wxml-->
<View className='select-car-page'>
  <NavBar back home title='请选择车型' />
  <View className='select-car-warp'>
    <SearchInput bindTire={bindTire} />
    <BrandList />
  </View>
</View>

在我们的页面中,使用了3个函数组件NavBarSearchInputBrandList,但是在Taro中的实际渲染,并没有将这3个组件作为小程序原生组件来渲染。真实的渲染结果如下:

c1.png

所以,我们在这些组件内部使用这些api时,还是可以直接使用Taro.Api进行使用。

但是有2种情况下,是比较特殊的,需要获取到当前小程序组件的实例。

  • dom层级超过指定层级时,在Taro官网中,也有说明,如下:

对于不支持模板递归的小程序(微信、QQ、京东小程序),在 DOM 层级达到一定数量后,Taro 会使用原生自定义组件协助递归。 简单理解就是 DOM 结构超过 N 层后,会使用原生自定义组件进行渲染。N 默认是 16 层,可以通过修改配置项 baseLevel 修改 N

  • 手动使用了CustomWrapper组件。

为了解决全局配置不灵活的问题,我们增加了一个基础组件 CustomWrapper。它的作用是创建一个原生自定义组件,对后代节点的 setData 将由此自定义组件进行调用,达到局部更新的效果。

其实上面2中场景,都是使用了小程序原生自定义组件,导致出现不同作用域,无法直接通过Taro.createSelectorQuery获取组件内的dom节点。第1种是被动使用,通常不容易被注意到;第2种是主动使用,通常用来性能优化。所以我们在这种组件内部,需要通过组件实例来调用相应的api

使用CustomWrapper 组件 包裹遇到更新性能问题的模块,可以提升更新时的性能

可以再看下,当我们使用 CustomWrapper 包裹我们组件内容时,渲染的结果如下:

c2.png

可以看到,实际会使用小程序的自定义组件CustomWrapper来进行渲染。

那当我们遇到这种必须使用自定义组件的时候,在函数组件中,应该如何获取当前组件的实例呢?

获取小程序组件实例方法

可以先获取到页面实例,在通过页面实例的selectComponent方法获取组件实例,如下:

<!--BrandList组件内容-->
<CustomWrapper id='brandList'>
    <!--组件内部内容-->
    <>...</>
</CustomWrapper>
// 获取当前自定义组件实例
const page = Taro.getCurrentInstance().page;
const that = page.selectComponent('#brandList');
// 通过组件实例调用相应的api
that.createSelectorQuery()

这种方式如果在嵌套使用 CustomWrapper 时,深层级的组件,就无法直接通过页面实例来获取了,需要通过父组件实例获取。

网上看到有些历史方案,在函数组件中使用 TarouseScope hook ,在class组件中使用 this.$scope,来获取当前作用域,但是目前的Taro3.x版本中已经没有这个hook和属性了。希望后续能够有更好的解决方案。

参考