我有一个弹出列表,它是一个div,其中包含一个垂直列表的 children div.我添加了上/下键盘导航,以更改当前高亮显示的子元素.

现在,如果我按下向下键足够多次,高亮显示的项目将不再可见.如果滚动视图,向上键也会发生同样的情况.

在React中,自动将子元素div滚动到视图中的正确方式是什么?

推荐答案

我假设你有一些List分量和一些Item分量.我这样做的方式是让物品知道它是否处于活动状态;如果有必要,该项目将要求列表滚动到视图中.考虑下面的伪代码:

class List extends React.Component {
  render() {
    return <div>{this.props.items.map(this.renderItem)}</div>;
  }

  renderItem(item) {
    return <Item key={item.id} item={item}
                 active={item.id === this.props.activeId}
                 scrollIntoView={this.scrollElementIntoViewIfNeeded} />
  }

  scrollElementIntoViewIfNeeded(domNode) {
    var containerDomNode = React.findDOMNode(this);
    // Determine if `domNode` fully fits inside `containerDomNode`.
    // If not, set the container's scrollTop appropriately.
  }
}

class Item extends React.Component {
  render() {
    return <div>something...</div>;
  }

  componentDidMount() {
    this.ensureVisible();
  }

  componentDidUpdate() {
    this.ensureVisible();
  }

  ensureVisible() {
    if (this.props.active) {
      this.props.scrollIntoView(React.findDOMNode(this));
    }
  }
}

更好的解决方案可能是让列表负责将项目滚动到视图中(而项目不知道它甚至在列表中).为此,您可以将ref属性添加到某个项目中,并使用该属性找到它:

class List extends React.Component {
  render() {
    return <div>{this.props.items.map(this.renderItem)}</div>;
  }

  renderItem(item) {
    var active = item.id === this.props.activeId;
    var props = {
      key: item.id,
      item: item,
      active: active
    };
    if (active) {
      props.ref = "activeItem";
    }
    return <Item {...props} />
  }

  componentDidUpdate(prevProps) {
    // only scroll into view if the active item changed last render
    if (this.props.activeId !== prevProps.activeId) {
      this.ensureActiveItemVisible();
    }
  }

  ensureActiveItemVisible() {
    var itemComponent = this.refs.activeItem;
    if (itemComponent) {
      var domNode = React.findDOMNode(itemComponent);
      this.scrollElementIntoViewIfNeeded(domNode);
    }
  }

  scrollElementIntoViewIfNeeded(domNode) {
    var containerDomNode = React.findDOMNode(this);
    // Determine if `domNode` fully fits inside `containerDomNode`.
    // If not, set the container's scrollTop appropriately.
  }
}

如果不想通过计算来确定该项在列表 node 中是否可见,可以使用DOM method scrollIntoView()或特定于Webkit的scrollIntoViewIfNeeded,即has a polyfill available,以便在非Webkit浏览器中使用.

Reactjs相关问答推荐

导致类型错误的调度不是函数";

在Redux工具包查询中,是否可以将标记应用到API切片内的所有端点?

为什么我的标签在Redux API中不能正常工作?

如何在React中的textarea中显示字符数?

如何在react 流中使用文本区域和改变 node 的输入大小?

Reaction Google Maps API无法获取标题

Reaction-路由-DOM v6与v5

如何在物料界面react 的多选菜单中设置最大 Select 数限制

从 MongoDB createAt 字段中分割精确时间

验证 Yup 中的对象项

为什么在 React 的 useEffect 中使用 onAuthStateChanged ?

使用reactrouterdom时显示"对象无效作为React子组件"错误

无法使axiosmockadapter正常工作

有没有办法在用户离开页面时防止输入模糊?

顶点图表甜甜圈项目边框半径

RTK 查询Mutations 在 StrictMode 中执行两次

map 未显示在react 传单中

react 本机日历

如何通过 Material Ui 设计将 Accordion 添加到您的 React 项目中?

如何防止 mui x-date-picker 被截断?