taro h5的scroll-view组件,scroll-top判断是否触发元素滚动的条件有问题

gywdnpxw  于 2个月前  发布在  其他
关注(0)|答案(2)|浏览(24)

相关平台

H5

浏览器版本: Chrome 123.0.6312.58
使用框架: React

复现步骤

  1. h5的scroll-view组件,声明了scroll-top属性。
  2. 触发滚动后,滚动元素自身的scrollTop改变了,但是没有改变state的scrollTop。
  3. 这时候重新触发了页面render,state数据层的scroll-top并没有改变,但是触发了scroll-view的滚动。

期望结果

理论上scroll-top应该是数据驱动的。拿state的scroll-top去和dom元素实时的scroll-top比较,来判断是否需要触发滚动,这个逻辑本身上是有问题的。
期望state的scroll-top没有改变的情况下,不触发元素的滚动。

实际结果

state的scroll-top没有改变的情况下,其他操作引起的render触发了元素的滚动。

环境信息

Taro CLI 3.6.24 environment info:
    System:
      OS: macOS 14.1
      Shell: 5.9 - /bin/zsh
    Binaries:
      Node: 14.21.3 - ~/.nvm/versions/node/v14.21.3/bin/node
      Yarn: 1.22.19 - ~/.nvm/versions/node/v16.17.1/bin/yarn
      npm: 6.14.18 - ~/.nvm/versions/node/v14.21.3/bin/npm
    npmPackages:
      @tarojs/cli: 3.6.24 => 3.6.24 
      @tarojs/components: 3.6.24 => 3.6.24 
      @tarojs/helper: 3.6.24 => 3.6.24 
      @tarojs/mini-runner: 3.6.24 => 3.6.24 
      @tarojs/plugin-framework-react: 3.6.24 => 3.6.24 
      @tarojs/plugin-platform-h5: 3.6.24 => 3.6.24 
      @tarojs/plugin-platform-weapp: 3.6.24 => 3.6.24 
      @tarojs/react: 3.6.24 => 3.6.24 
      @tarojs/router: 3.6.24 => 3.6.24 
      @tarojs/runtime: 3.6.24 => 3.6.24 
      @tarojs/service: 3.6.24 => 3.6.24 
      @tarojs/shared: 3.6.24 => 3.6.24 
      @tarojs/taro: 3.6.24 => 3.6.24 
      @tarojs/taro-loader: 3.6.24 => 3.6.24 
      @tarojs/webpack5-runner: 3.6.24 => 3.6.24 
      babel-preset-taro: 3.6.24 => 3.6.24 
      eslint-config-taro: 3.6.24 => 3.6.24 
      react: ^18.2.0 => 18.2.0
093gszye

093gszye1#

taro/packages/taro-components-react/src/components/scroll-view/index.tsx

Lines 114 to 128 in 383f0da

| | if(props.scrollY&&typeofprops.scrollTop==='number'&&props.scrollTop!==this._scrollTop){ |
| | if(isInit){ |
| | setTimeout(()=>scrollVertical.bind(this)(props.scrollTop,isAnimation),10) |
| | }else{ |
| | scrollVertical.bind(this)(props.scrollTop,isAnimation) |
| | } |
| | } |
| | // X 轴滚动 |
| | if(props.scrollX&&typeofprops.scrollLeft==='number'&&props.scrollLeft!==this._scrollLeft){ |
| | if(isInit){ |
| | setTimeout(()=>scrollHorizontal.bind(this)(props.scrollLeft,isAnimation),10) |
| | }else{ |
| | scrollHorizontal.bind(this)(props.scrollLeft,isAnimation) |
| | } |
| | } |

这里判断 props.scrollTop !== this._scrollTop ,但是 this._scrollTop 在onScroll中实时变更;

taro/packages/taro-components-react/src/components/scroll-view/index.tsx

Lines 172 to 188 in 383f0da

| | const_onScroll=e=>{ |
| | const{ scrollLeft, scrollTop, scrollHeight, scrollWidth }=this.container |
| | this._scrollLeft=scrollLeft |
| | this._scrollTop=scrollTop |
| | Object.defineProperty(e,'detail',{ |
| | enumerable: true, |
| | writable: true, |
| | value: { |
| | scrollLeft, |
| | scrollTop, |
| | scrollHeight, |
| | scrollWidth |
| | } |
| | }) |
| | upperAndLowerThrottle(e) |
| | onScroll&&onScroll(e) |
| | } |

导致了props.scrollTop没有改变的情况下,仍然会触发dom元素的滚动。

符合数据流驱动的修改如下:

// Y 轴滚动
      if (props.scrollY && typeof props.scrollTop === 'number' && props.scrollTop !== this._scrollTop) {
        if (isInit) {
          setTimeout(() => scrollVertical.bind(this)(props.scrollTop, isAnimation), 10)
        } else {
          scrollVertical.bind(this)(props.scrollTop, isAnimation)
        }
       this._scrollTop = props.scrollTop
      }
      // X 轴滚动
      if (props.scrollX && typeof props.scrollLeft === 'number' && props.scrollLeft !== this._scrollLeft) {
        if (isInit) {
          setTimeout(() => scrollHorizontal.bind(this)(props.scrollLeft, isAnimation), 10)
        } else {
          scrollHorizontal.bind(this)(props.scrollLeft, isAnimation)
        }
       this._scrollLeft = props.scrollLeft
      }
mm5n2pyu

mm5n2pyu2#

我也遇到了一样的问题

相关问题