当前位置: 首页 > 知识库问答 >
问题:

使用window.scrollTo将导航栏滚动到div无效

单勇
2023-03-14

我有一个导航条函数组件,它通过onclick回调将链接的名称传递给父组件,并进一步传递给主应用程序组件。应用程序组件有一个名为链接和关联ref的对象。应用程序组件中的onclick回调根据底层组件传递给它的链接名从对象获取ref,并调用window.scrollTo。window.scrollTo在您第一次单击某个链接时起作用,如果从粘性导航栏单击了另一个链接,则当页面滚动时,window不会再次滚动,而是返回到(0,0),从那里单击相同的链接起作用。

//在App组件中回调。

manageContent(link){

   console.log(this.linksData[link].current)

    window.scrollTo({
        top: this.linksData[link].current.offsetTop,
        left: 0,
        behavior: 'smooth'
     })    
}

上述函数被传递给Header组件

<Header links={data} onclick={this.manageContent} ref={this.headerRef}/>

在标题中,链接是使用NavLink函数组件创建的,onClick将返回链接名称。

我做错了什么,为什么scrollTo在页面滚动到顶部而不是从页面中间或滚动位置进行第二次单击时工作。

我也尝试了其他的滚动功能,只是滚动到滚动,而滚动选项、滚动到视图、移动到等等根本不起作用。

我在控制台和触发窗口中打印了offsetTop。scrollTo(0,“offsetTop printed in console”),工作正常,没有问题。

这是代码。

App.js

class App extends React.Component {

  constructor(props){
    super(props);
    this.manageContent = this.manageContent.bind(this)

    this.state={}
    this.sectionRef1 = React.createRef();
    this.sectionRef2 = React.createRef();
    this.sectionRef3 = React.createRef();
    this.sectionRef4 = React.createRef();
    this.sectionRef5 = React.createRef();    
    this.headerRef = React.createRef();    
    this.heroRef = React.createRef();
  }
  manageContent(key){
    console.log(key)
    this.setState({key:key});
  }

setActivePage = (key) => {
    let refList = [this.sectionRef1,this.sectionRef2,this.sectionRef3,this.sectionRef4,this.sectionRef5]
    console.log(key)
    console.log(refList[key].current)
    if (refList[key].current){
        window.scrollTo({behavior: "smooth",top: refList[key].current.offsetTop})

    }
}
componentDidUpdate(prevProps, prevState) {  
  console.log("comp updated")
  this.setActivePage(this.state.key)
}
/*
componentDidMount(){
  window.addEventListener('scroll', this.scrollListener)
}
componentWillUnmount() {
  window.removeEventListener('scroll', this.scrollListener)
}    
*/
  render(){     
    return (
      <div className="bp-container-full bp-typography" key="app">
        <Header links={data.links} onclick={this.manageContent} ref={this.headerRef}/>
        <main key="main">
            <HeroSection ref={this.heroRef}/>
            <div className="bp-main">
            <section key="home"className="page" ref={this.sectionRef1}>
              <Home/>
            </section>
            <section key="aboutme" className="page" ref={this.sectionRef2}>
              <AboutMe/>
            </section>
            <section key="sitedetails" className="page" ref={this.sectionRef4}>  
              <SiteDetails/>
            </section>
            <section key="contact" className="page" ref={this.sectionRef5}>  
              <ContactForm/>
            </section>
            </div>
        </main>
        <Footer/>  
      </div>
    );
  }

}
export default App;

Header.js

class Header extends React.Component {
    constructor(props) {
        super(props);
        console.log(props)
        this.linkRef = React.createRef()
        this.state = {isOpen:false};
        this.headerRef = React.createRef()
    }

    render() {      
        const navlink = data.links.map((link,key)=>{ 
            return(
            <a href="#" key={link} ref={this.linkRef}
                    className="nav-list-item bp-upper"
                    onClick={() => this.props.onclick(key)}>
                  {link}
            </a>
        )})
        return (
            <header key="header-key" className={classnames("bp-header","bp-header-fixed",
                            {"is-scrolled":this.state.scrolled})} ref={this.headerRef}>
                <button className={classnames("bp-mobile-menu",{"is-open":this.state.isOpen})} onClick={()=>{this.setState({isOpen:!this.state.isOpen})}}>
                  <i className={classnames("fas", {"fa-bars":!this.state.isOpen, "fa-times":this.state.isOpen})}></i>
                </button>                            
                <div className={classnames("nav", "nav-align-centre",{"is-open":this.state.isOpen})}>
                    <nav className="nav-list nav-primary">
                        {navlink}
                    </nav>
                </div>
            </header>
        )
    }
}
export default Header;

共有3个答案

强金鑫
2023-03-14

刚刚发现这个react ref with focus()在没有setTimeout(我的示例)的情况下无法工作,是的,这很有帮助。setTimeOut确实提供了一种修复方法,但这篇文章也解释了我的代码可能有什么问题。

姜杜吟
2023-03-14

根据你提供的代码,不清楚什么地方可能出错。我的假设是,你分配裁判或处理回叫的方式有问题。

下面是一个工作沙箱,它将向您展示使其工作可能需要的所有代码:https://codesandbox.io/s/navbar-click-scroll-into-section-us8y7

基本上与您的应用程序具有相同的布局。我们有一个带有链接的导航栏/标题,当点击其中一个时,我们会触发一个回调并找到相关的ref。然后滚动到指定了该参考的部分。

import React from "react";
import ReactDOM from "react-dom";
import Header from "./Header";
import HowItWorks from "./HowItWorks";
import BrowserCatalogue from "./BrowserCatalogue";
import Contact from "./Contact";
import Woof from "./Woof";

import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: null
    };
  }
  //refs
  howItWorks = React.createRef();
  browserCatalogue = React.createRef();
  contact = React.createRef();
  woof = React.createRef();

  changeSelection = index => {
    this.setState({
      selected: index
    });
  };

  componentDidUpdate(prevProps, prevState) {
    this.scrollToSection(this.state.selected);
  }

  scrollToSection = index => {
    let refs = [
      this.howItWorks,
      this.browserCatalogue,
      this.contact,
      this.woof
    ];

    if (refs[index].current) {
      refs[index].current.scrollIntoView({
        behavior: "smooth",
        nearest: "block"
      });
    }
  };

  render() {
    return (
      <div className="App">
        <div>
          <Header changeSelection={this.changeSelection} />
        </div>
        <div ref={this.howItWorks}>
          <HowItWorks />
        </div>
        <div ref={this.browserCatalogue}>
          <BrowserCatalogue />
        </div>
        <div ref={this.contact}>
          <Contact />
        </div>
        <div ref={this.woof}>
          <Woof />
        </div>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React from "react";

const Header = props => {
  const { changeSelection } = props;
  return (
    <div
      style={{
        background: "green",
        height: "50px",
        width: "100%",
        position: "fixed",
        top: "0"
      }}
    >
      <span onClick={() => changeSelection(0)}>Working</span>{" "}
      <span onClick={() => changeSelection(1)}>Catalogue</span>{" "}
      <span onClick={() => changeSelection(2)}>Contact</span>{" "}
      <span onClick={() => changeSelection(3)}>Woof</span>
    </div>
  );
};

export default Header;
陆阳曜
2023-03-14

最后在几乎写了整个应用程序多次之后发现了这个问题。

我的链接有一个href,是的,我很傻,使用href=“#”解决了这个问题,可能也解释了为什么它只需两次点击,而不是一次点击。

<a href="#" key={link} ref={this.linkRef}
                    className="nav-list-item bp-upper"
                    onClick={() => this.props.onclick(key)}>
                  {link}
            </a>
 类似资料:
  • 我使用引导为一个主题,我看到了这个网站:http://www.luatix.org/en/,我喜欢navbar上的效果。向下滚动时更改颜色并更改元素的颜色。 谢啦

  • 如何设置没有背景色的导航栏? 当在div之后向下滚动导航条时,导航条会得到一个新的背景颜色(导航条应该固定在顶部,我在引导中使用) 我尝试过一些教程,但没有成功。 这是网站:http://attafothman.olympe.in/ 我说的是上面那个黑色导航条。

  • 使用数据查看器的“导航栏”按钮,可以快捷方便地浏览文档或页。 按钮 描述 添加文档 - 输入一个新的文档。在使用数据查看器的任何时候,点击此按钮来得到一个空白的文档。 删除文档 - 删除一个现有的文档。 应用更改 - 应用已做的更改。 放弃更改 - 移除当前记录的全部编辑。 刷新 - 刷新数据。 停止 - 当从服务器加载大量数据时,停止加载。 第一页 - 移动到第一页。 上一页 - 移动到上一页。

  • 使用数据查看器的“导航栏”按钮,可以快捷方便地浏览记录或页。 按钮 描述 添加记录 - 输入一条新的记录。在使用数据查看器的任何时候,点击此按钮来得到一条空白的记录。 删除记录 - 删除一条现有的记录。 应用更改 - 应用已做的更改。 放弃更改 - 移除当前记录的全部编辑。 刷新 - 刷新数据。 停止 - 当从服务器加载大量数据时,停止加载。 第一页 - 移动到第一页。 上一页 - 移动到上一页。

  • 使用数据查看器的“导航栏”按钮,可以快捷方便地浏览文档或页。 按钮 描述 添加文档 - 输入一个新的文档。在使用数据查看器的任何时候,点击此按钮来得到一个空白的文档。 删除文档 - 删除一个现有的文档。 应用更改 - 应用已做的更改。 放弃更改 - 移除当前记录的全部编辑。 刷新 - 刷新数据。 停止 - 当从服务器加载大量数据时,停止加载。 第一页 - 移动到第一页。 上一页 - 移动到上一页。

  • 使用数据查看器的“导航栏”按钮,可以快捷方便地浏览记录或页。 按钮 描述 添加记录 - 输入一条新的记录。在使用表查看器的任何时候,点击此按钮来得到一条空白的记录。 删除记录 - 删除一个现有的记录。 应用更改 - 应用已做的更改。 放弃更改 - 移除当前记录的全部编辑。 刷新 - 刷新数据。 停止 - 当从服务器加载大量数据时,停止加载。 第一页 - 移动到第一页。 上一页 - 移动到上一页。