我有一个弹出列表,它是一个div
,其中包含一个垂直列表的 children div
.我添加了上/下键盘导航,以更改当前高亮显示的子元素.
现在,如果我按下向下键足够多次,高亮显示的项目将不再可见.如果滚动视图,向上键也会发生同样的情况.
在React中,自动将子元素div
滚动到视图中的正确方式是什么?
我有一个弹出列表,它是一个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浏览器中使用.