我有一个弹出列表,其中div包含子divs 的垂直列表。我添加了向上/向下键盘导航来更改当前突出显示的哪个孩子。
div
现在,如果我按下向下键的次数足够多,则突出显示的项目将不再可见。如果滚动视图,则向上键也会发生相同的情况。
在React中自动将孩子滚动div到视图中的正确方法是什么?
我假设您具有某种List组件和某种Item组件。我在一个项目中执行此操作的方式是让该项目知道它是否处于活动状态。该项目将要求列表在必要时将其滚动到视图中。考虑以下伪代码:
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属性添加到特定项目并使用以下内容找到它:
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. } }
如果您不希望做数学运算来确定该项是否在列表节点内可见,则可以使用DOM方法scrollIntoView()或特定于Webkit的Webkit scrollIntoViewIfNeeded,它可以使用polyfill,因此可以在非Webkit浏览器中使用它。
scrollIntoView()
scrollIntoViewIfNeeded