React:单击锚标记以停止页面重新加载以滚动

时间:2017-11-09 11:07:47

标签: javascript html5 reactjs react-router

我目前正在使用react来创建一个维基百科风格的网站。出于数据输入的原因,我从数据库中获取整个HTML,然后使用dangerouslySetInnerHTML来设置它的一部分,如下所示:

dangerouslySetInnerHTML={{ __html: this.props.section.text }}

现在页面中还有其他部分可以播放视频,但每次点击<a href="#id>样式标记(使用数据库设置)导航到同一页面的另一部分时,整个页面刷新。

这会产生问题,因为视频也会重新加载并从头开始播放。

有没有办法在没有完整页面重新加载的情况下使用危险设置的锚标签滚动到React页面的某些部分?

编辑:使用以下版本:

  

“react”:“^ 16.0.0”,“react-router-dom”:“^ 4.2.2”

5 个答案:

答案 0 :(得分:1)

您可以做的是将eventListener添加到您的组件,该组件会侦听href属性值以#开头的所有锚标记。

componentDidMount()方法中,选择<a>所有href="#..."个标记。您可以使用document.querySelectorAll("a[href^='#']")执行此操作。这将返回匹配的所有节点的数组。然后,您可以遍历它们并将eventListener附加到每个。

eventListener将侦听click并运行一个函数来阻止默认行为(重定向到另一个页面),而是推送到您的路由器。 (删除下面的评论)

class MyApp extends React.Component {

  constructor(props) {
    super(props);
  }

  componentDidMount() {
    document.querySelectorAll("a[href^='#']").forEach(node => {
      node.addEventListener('click', e => {
        e.preventDefault();
        console.log(e.target.href);
        //this.props.history.push(e.target.href);
      });
    })
  }
 
  render() {
    const myMarkup = "<ul><li><a href='#'>Page link 1</a></li><li><a href='#test'>Page link 2</a></li><li><a href='https://google.com'>External link</a></li></ul>";
    return(
      <div id="container" dangerouslySetInnerHTML={{__html: myMarkup}}></div>
    );
  }
}
 
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

上面的代码段假设您使用的是withRouter HOC。否则推送将无效。有关详细信息,请参阅我对How to push to History in React Router v4?的回答。

答案 1 :(得分:0)

捕获默认的eventhandler并自己处理事件处理。你可以将它放在componentDidMount生命周期钩子中。同时删除componentWillUnmount

中的这些处理程序
var aTags = document.querySelectorAll('a[href]'); //use apt selector for you section


     aTags.forEach(aTag =>aTag.addEventListener('click',function(e){
          e.preventDefault();
          e.nativeEvent.stopImmediatePropagation()
          e.stopPropagation()
          var href = e.target.href;
          history.pushState({},'',href);
        }));

答案 2 :(得分:0)

由于你的问题有标签&#34; react-router&#34;我假设您在应用程序中使用它,我还假设您使用的是v4.x的最新版本。

我过去解决这个问题的方法是使用React Router Hash link包。正如他们的文档中所述,您可以像这样使用它(将您的<a href="#id">替换为<Link>):

// In YourComponent.js
...
import { HashLink as Link } from 'react-router-hash-link';
...
// Use it just like a RRv4 link (to can be a string or an object, see RRv4 api for details):
<Link to="/some/path#with-hash-fragment">Link to Hash Fragment</Link>

答案 3 :(得分:0)

要添加到@Shishir Arora所说的内容中,请使用package main import "fmt" func main() { var a, b int var c = &b switch *c { case b: fmt.Println("b") case a: fmt.Println("a") default: fmt.Println("c") } } 之类的字词,而不要使用history.pushState({},'',href);

以下是使用jQuery的完整组件的代码:

document.getElementById(hash.replace('#', '')).scrollIntoView();

jQuery有助于捕获import React, { useEffect } from 'react'; import $ from 'jquery'; const handleAnchorClick = e => { e.preventDefault(); e.stopPropagation(); const hash = e.currentTarget.hash; document.getElementById(hash.replace('#', '')).scrollIntoView(); // Alternatively use jQuery for the above line: $(hash).get(0).scrollIntoView(); }; export default ({ response, url, search }) => { useEffect(() => { $('#article-content').on('click', 'a[href^="#"]', handleAnchorClick); return () => { $('#article-content').off('click', 'a[href^="#"]', handleAnchorClick); }; }, [response]); return ( <div> <div id='article-content' dangerouslySetInnerHTML={{__html: response}} /> </div> ); }; ,由于标签中嵌套了一个元素,因此无法与@Shishir的原始答案以相同的方式捕获。

答案 4 :(得分:-1)

由于您使用的是React Router v4,为什么不使用Link

...
import { Link } from 'react-router-dom';
... 
<Link to={{
  pathname: '/courses',
  search: '?sort=name',
  hash: '#the-hash',
  state: { fromDashboard: true }
}}/>

您可以找到文档here