Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

virtual list scrollTo 后的滚动会额外触发一次 render,并导致 scrollView 回到顶部 #8560

Closed
GitaiQAQ opened this issue Jan 20, 2021 · 6 comments
Labels
F-react Framework - React T-weapp Target - 编译到微信小程序 V-3 Version - 3.x

Comments

@GitaiQAQ
Copy link
Contributor

相关平台

微信小程序

复现仓库

https://gist.github.com/GitaiQAQ/e5b768898325031dcd079eea22c4916a
小程序基础库: 2.14.4
使用框架: React

复现步骤

  • 点击 test,scrollTo 100, scrollTop 变成 100
  • 向下或者向上滚动
  • 会触发 render 导致 scrollTop 变成 0

期望结果

scrollTop 变成 100

实际结果

scrollTop 变成 0

环境信息

👽 Taro v3.0.18


  Taro CLI 3.0.18 environment info:
    System:
      OS: macOS 10.15.7
      Shell: 5.7.1 - /bin/zsh
    Binaries:
      Node: 14.5.0 - ~/.nvm/versions/node/v14.5.0/bin/node
      Yarn: 1.22.4 - /usr/local/bin/yarn
      npm: 6.14.5 - ~/.nvm/versions/node/v14.5.0/bin/npm

@taro-bot2 taro-bot2 bot added F-react Framework - React T-weapp Target - 编译到微信小程序 V-3 Version - 3.x labels Jan 20, 2021
@GitaiQAQ
Copy link
Contributor Author

GitaiQAQ commented Jan 20, 2021

可以通过在 createListComponent 增加 lockedScrollOffset 来提供一个稳定的 scrollOffset,来解决这个问题

this._onScrollVertical = event => {
  const {
    clientHeight,
    scrollHeight,
    scrollTop
  } = event.currentTarget
  this.setState(prevState => {
    if (prevState.scrollOffset === scrollTop) {
      // Scroll position may have been updated by cDM/cDU,
      // In which case we don't need to trigger another render,
      // And we don't want to update state.isScrolling.
      return null
    } // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.

    const scrollOffset = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight))
    return {
      isScrolling: true,
      scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
      scrollOffset,
+     lockedScrollOffset: (prevState.lockedScrollOffset === scrollOffset ? scrollOffset + 0.1 : scrollOffset),
      scrollUpdateWasRequested: false
    }
  }, this._resetIsScrollingDebounced)
}
render () {
      ...
   if (scrollUpdateWasRequested) {
        if (isHorizontal) {
            outerElementProps.scrollLeft = scrollOffset
        } else {
            outerElementProps.scrollTop = scrollOffset
        }
+    } else {
+       if (isHorizontal) {
+           outerElementProps.scrollLeft = lockedScrollOffset
+       } else {
+           outerElementProps.scrollTop = lockedScrollOffset
+       }
+.   }
      ...
}

@ZakaryCode
Copy link
Contributor

未能复现到该问题😂

@ZakaryCode
Copy link
Contributor

知道你说的是啥了,确实是会有一点影响体验,PR 将被合入

@MarshallYang
Copy link

可以通过在 createListComponent 增加 lockedScrollOffset 来提供一个稳定的 scrollOffset,来解决这个问题

this._onScrollVertical = event => {
  const {
    clientHeight,
    scrollHeight,
    scrollTop
  } = event.currentTarget
  this.setState(prevState => {
    if (prevState.scrollOffset === scrollTop) {
      // Scroll position may have been updated by cDM/cDU,
      // In which case we don't need to trigger another render,
      // And we don't want to update state.isScrolling.
      return null
    } // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.

    const scrollOffset = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight))
    return {
      isScrolling: true,
      scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
      scrollOffset,
+     lockedScrollOffset: (prevState.lockedScrollOffset === scrollOffset ? scrollOffset + 0.1 : scrollOffset),
      scrollUpdateWasRequested: false
    }
  }, this._resetIsScrollingDebounced)
}
render () {
      ...
   if (scrollUpdateWasRequested) {
        if (isHorizontal) {
            outerElementProps.scrollLeft = scrollOffset
        } else {
            outerElementProps.scrollTop = scrollOffset
        }
+    } else {
+       if (isHorizontal) {
+           outerElementProps.scrollLeft = lockedScrollOffset
+       } else {
+           outerElementProps.scrollTop = lockedScrollOffset
+       }
+.   }
      ...
}

3.0.28 版本后 VirtualList 滚动的时候支付宝小程序平台下会有抖动的现象发生。

@ihwf
Copy link

ihwf commented Apr 10, 2021

微信小程序内也出现抖动问题

@17
Copy link

17 commented Jun 10, 2021

最新 3.2.10 仍然有这个问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-react Framework - React T-weapp Target - 编译到微信小程序 V-3 Version - 3.x
Projects
None yet
Development

No branches or pull requests

5 participants