我有一个父组件,该组件在标头下方呈现一个子组件。标题具有一个按钮,单击该按钮时应滚动到相应子组件的一部分。
现在,我正在尝试更改按钮单击的状态,并将此新状态作为道具从父级传递到子级组件。然后,在子组件中,我尝试使用向下传递的prop作为要滚动到的部分的标识符来运行scroll()函数。
父组件:
handleSelected = event => {
this.setState({ selected: event.currentTarget.value });
};
<Button value="sectionOne" onClick={this.handleSelected} />
<Child loadSelected={() => this.state.selected}</Child>
子组件:
ComponentDidMount() {
let selected = this.props.loadSelected();
this.handleNavigate(selected);
}
handleNavigate = section => {
let el = document.getElementById(section);
window.scrollTo({
behavior: "smooth",
left: 0,
top: el.offsetTop
});
};
....
....
....
<div id="sectionOne" />
答案 0 :(得分:2)
直接与DOM中的元素进行交互时,通常需要这样做via refs,而不是通过诸如getElementById()
,querySelectorAll()
之类的方法从DOM查询元素等
您可以通过多种方式将refs
集成到应用程序中以实现所需的功能-一种方法是为每个部分创建一个ref
,并将每个部分及其相应的ref存储在父级中(标题?)组件,然后从父级而不是从子级handleNavigate()
,如下所示:
class Parent extends React.Component {
constructor(props) {
super(props)
/* Mock sections data */
this.sections = [
{
name : "Foo",
color: "pink",
ref : React.createRef() /* Ref per section */
},
{
name : "Bar",
color: "lightblue",
ref : React.createRef()
},
{
name : "Cat",
color: "lightgreen",
ref : React.createRef()
}];
}
/* Move into parent/header */
handleNavigate = section => {
/*
Access the "current element" of this sections ref.
Treat this as the element of the div for this section.
*/
let el = section.ref.current;
window.scrollTo({
behavior: "smooth",
left: 0,
top: el.offsetTop
});
};
render() {
return (
<div>
<nav>
<h2>Menu</h2>
{
this.sections.map(section =>
<button onClick={() => this.handleNavigate(section)}>
{section.name}
</button>)
}
</nav>
<div>
{ this.sections.map(section => <Child section={section} />)}
</div>
</div>
)
}
}
class Child extends React.Component {
render() {
const { section } = this.props;
const style = {
padding:"15rem 0", background : section.color
};
return <div ref={ section.ref } style={ style }>
Section for { section.name }
</div>
}
}
引用提供了一种与真实DOM元素进行交互的可靠方式,该元素表示组件渲染结果的一部分。在上面的代码中,ref与Child
的div相关联。 ref的current
字段提供对该孩子div的实际DOM元素的访问,可以将其传递给scrollTo()
方法以实现您想要的平滑滚动动画。
有关此方法的有效示例,see this fiddle。希望有帮助!