Taro: IntersectionObserver 的 observe 方法不起作用

Created on 1 Dec 2020  ·  6Comments  ·  Source: NervJS/taro


相关平台

字节跳动小程序

复现仓库

https://github.com/Lyokoo/taro-demo
小程序基础库: 1.80.1.17
使用框架: React

复现步骤

页面往下滚动, 直到出现一个绿色的 View 盒子

期望结果

触发 IntersectionObserver 回调

实际结果

没有触发 IntersectionObserver 回调

环境信息

👽 Taro v3.0.16


  Taro CLI 3.0.16 environment info:
    System:
      OS: macOS 10.14.6
      Shell: 5.3 - /bin/zsh
    Binaries:
      Node: 12.13.0 - ~/.nvm/versions/node/v12.13.0/bin/node
      Yarn: 1.22.4 - ~/.nvm/versions/node/v12.13.0/bin/yarn
      npm: 6.12.1 - ~/.nvm/versions/node/v12.13.0/bin/npm
    npmPackages:
      @tarojs/components: 3.0.16 => 3.0.16
      @tarojs/mini-runner: 3.0.16 => 3.0.16
      @tarojs/react: 3.0.16 => 3.0.16
      @tarojs/runtime: 3.0.16 => 3.0.16
      @tarojs/taro: 3.0.16 => 3.0.16
      @tarojs/webpack-runner: 3.0.16 => 3.0.16
      babel-preset-taro: 3.0.16 => 3.0.16
      eslint-config-taro: 3.0.16 => 3.0.16
      react: ^16.10.0 => 16.14.0

F-react T-tt V-3

Most helpful comment

@Lyokoo 需要改两个地方

  1. this 指向你编写的 React 实例,不是小程序的 Page 对象。需要通过 Taro.getCurrentInstance().page 获取当前小程序页面实例。
  2. 获取小程序 DOM 需要在 onReady 生命周期,componentDidMount 只是 React 完成渲染 Taro 的虚拟 dom,此时还没 setData 结束。
import React, { Component } from 'react'
import { View, Canvas } from '@tarojs/components'
import Taro from '@tarojs/taro'
import './index.scss'

export default class Index extends Component {
  current = Taro.getCurrentInstance()
  onReady () {
    console.log('didMount', this.current);
    // @ts-ignore
    const io = Taro.createIntersectionObserver(this.current.page);
    console.log('io 实例:', io);
    io.relativeToViewport().observe('.circle-container', res => {
      console.log('res:', res);
    });
  }

  render() {
    return (
      <View className='index'>
        <View>👇👇👇 向下滚动 👇👇👇👇</View>
        <View>👇👇👇 向下滚动 👇👇👇👇</View>
        <View>👇👇👇 向下滚动 👇👇👇👇</View>
        <View
          onClick={() => {
            // @ts-ignore
            Taro.showToast({
              title: 'aaaa'
            });
          }}
          className='circle-container'
          style={{
            height: '100rpx',
            backgroundColor: 'green',
            marginTop: '2000rpx',
            marginBottom: '100rpx',
            color: '#fff'
          }}
        >
          我的出现有触发 callback 吗?
        </View>
      </View>
    )
  }
}

All 6 comments

@Lyokoo 需要改两个地方

  1. this 指向你编写的 React 实例,不是小程序的 Page 对象。需要通过 Taro.getCurrentInstance().page 获取当前小程序页面实例。
  2. 获取小程序 DOM 需要在 onReady 生命周期,componentDidMount 只是 React 完成渲染 Taro 的虚拟 dom,此时还没 setData 结束。
import React, { Component } from 'react'
import { View, Canvas } from '@tarojs/components'
import Taro from '@tarojs/taro'
import './index.scss'

export default class Index extends Component {
  current = Taro.getCurrentInstance()
  onReady () {
    console.log('didMount', this.current);
    // @ts-ignore
    const io = Taro.createIntersectionObserver(this.current.page);
    console.log('io 实例:', io);
    io.relativeToViewport().observe('.circle-container', res => {
      console.log('res:', res);
    });
  }

  render() {
    return (
      <View className='index'>
        <View>👇👇👇 向下滚动 👇👇👇👇</View>
        <View>👇👇👇 向下滚动 👇👇👇👇</View>
        <View>👇👇👇 向下滚动 👇👇👇👇</View>
        <View
          onClick={() => {
            // @ts-ignore
            Taro.showToast({
              title: 'aaaa'
            });
          }}
          className='circle-container'
          style={{
            height: '100rpx',
            backgroundColor: 'green',
            marginTop: '2000rpx',
            marginBottom: '100rpx',
            color: '#fff'
          }}
        >
          我的出现有触发 callback 吗?
        </View>
      </View>
    )
  }
}

@Chen-jj 又遇到个问题, 就是我在子组件中使用 useReady, 但是如果这个子组件是用 state 来控制条件渲染的, 这种情况 useReady 钩子不会被触发, 有没有办法解决? 😭

componentDidUpdate() {
  Taro.nextTick(() => {
    // .....
  })
}

@Chen-jj 可以, 学习了!! 打扰再问最后一个问题, 我用 IntersectionObserver 封装了一个图片懒加载组件, observe 函数传入的都是同一个 className, 如下面的 ".box" , 如果组件使用多次, 那么 className 就出现多次, 这里有没有办法做到隔离; 目前只要有一个出现, 就触发多次

  return (
    <View className='box'>
      {/* 这里放图片 */}
    </View>
  );

不太清楚,看看 API 的用法吧,也可以写个原生 demo 测试一下。

@Lyokoo 请问你的问题解决了么,你的图片懒加载组件是如何实现的啊,请教一下

Was this page helpful?
0 / 5 - 0 ratings