重新排序时在 React 归零滚动位置 A 中列出(在 Chrome 72.0 中,在 Mac 上)

Kev*_*lan 0 html javascript reactjs

我看到列表滚动位置有一些奇怪的行为

在这个小提琴中,我有一个简单的 React 组件,它显示 20 个项目的列表,然后 5 秒后将项目 10 移动到列表顶部。

class List extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
        done: false,
        items: [
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        10,
        11,
        12,
        13,
        14,
        15,
        16,
        17,
        18,
        19,
        20,
      ]
    }
  }

  componentDidMount() {
    window.setTimeout(this._update, 5000)
  }

  render() {
    return (
      <ul className={ this.state.done ? 'done' : 'not_done' }>
        { this.state.items.map((x) => (
            <li 
            key={ `item_${ x }` } 
            className={ `item_${ x }` }
          >
            { x }
          </li>
        )) }
      </ul>
    )
  }

  _update = () => {
    console.log('_UPDARE')
    this.setState({
      done: true,
        items: [
        10,
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        11,
        12,
        13,
        14,
        15,
        16,
        17,
        18,
        19,
        20,
      ]
    })
  }
}

ReactDOM.render(<List />, document.querySelector("#app"))
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/5o2x4bvf/

如果向下滚动以使项目 10 在重新排序发生时在视口中可见,则滚动位置将重置为零。

如果项目 10 不可见(无论视口在其上方还是下方),则滚动位置不会归零,这是预期的行为。

我只在 Chrome (72.0) 中注意到这一点,在 Firefox 或 Safari 中没有注意到。

我在 Vanilla JS 中做了一个替代实现,但这种情况没有发生:https ://jsfiddle.net/47rscqdy/2/

我单步查看代码,发现 React 进行了效率较低的重新排序。它将项目 1-9 移动到项目 11 之前,而不是仅将项目 10 移到前面。此 Vanilla JS SSCE 演示了该问题 https://jsfiddle.net/t9hfsqyp/1/

有人有什么想法吗?

Kev*_*lan 7

嗯,那是一个兔子洞!

事实证明,这是由于 Chrome 在版本 56 中引入的滚动锚定功能,可以使用以下 css 在容器上禁用该功能:

overflow-anchor: none;
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/qcfk3hwr/