React Link与a标签以及箭头函数的区别

47

我刚开始学习React Router。

我有两个问题。使用<Link to="/page"><a href="page">有什么区别?两者都会向/page发出相同的请求,但当我嵌套路由时,使用<a href="page">会导致错误,而使用<Link to="/page">则可以正常工作。我不明白,既然它们渲染成完全相同的URL,为什么会有任何差异?

第二个问题是React Router v4文档中的奇怪箭头函数。

const About = () => (
  <div>
    <h2>About</h2>
  </div>
)

我知道() => {}是ES6中的新内容,但我找不到有关括号而非圆括号的任何信息。它们是什么?

编辑

我的index.js类(我已经导入了所有内容)

render((
    <Router>
        <div>
            <Route component={App}/>
        </div>
    </Router>
), document.getElementById('root')
);

我的App.js类

class App extends Component {
render() {
    return (
        <div className="container">
            <header>
                <span className="icn-logo"><i className="material-icons">code</i></span>
                <ul className="main-nav">
                    <li><Link to="/">Home</Link></li>
                    <li><Link to="/about">About</Link></li>
                    <li><Link to="/teachers">Teachers</Link></li>
                    <li><Link to="/courses">Courses</Link></li>
                </ul>
            </header>
            <Route exact path="/" component={Home}/>
            <Route path="/about" component={About}/>
            <Route path="/teachers" component={Teachers}/>
            <Route path="/courses" component={Course}/>
        </div>
    );
}
}

export default App;
我遇到的错误是:在浏览器中尝试访问“localhost:8080/about”时,出现“Cannot GET /about”的提示。但是,当我点击“about”按钮时,它会跳转到完全相同的URL“/about”,并且正确呈现。

2
我有点困惑,因为 () 是圆括号...所以你知道大括号 {},你知道箭头函数中何时隐含了一个 return,以及如果需要返回值时何时需要它吗?你还知道在箭头函数中何时会使用 () => ({}); 吗?哦,基本上,那个函数只是返回 <div> <h2>About</h2> </div> - Jaromanda X
@JaromandaX 抱歉,我把词汇搞混了。但是是的,那就是我要找的。谢谢。 - forJ
4个回答

82

也许有点晚了,不知道你是否已经解决了问题。以下是我的观点:

首先:

使用<Link to="/page"><a href="page">有什么区别?

  • 表面上看,你似乎在比较不同的东西。锚标签中的路径是相对路径,而Link中的路径是绝对路径(这样做是正确的,我认为react-router尚不支持相对路径)。这会导致的问题是,假设你在/blah页面,点击Link会跳转到/page页面,但是点击<a href='page' />会跳转到/blah/page页面。虽然这可能不是一个问题,因为你确认了URL的正确性,但还是值得注意。
  • 更深入的区别,只是@Dennis的答案(以及他指向的文档)的一个附加功能,就是当你已经处于与Link指向的路由相匹配的路由中时,如果Link指向的是/page或甚至/page/:id,这不会触发完整的页面刷新,而<a />标签自然会。请参见Github上的问题

我使用的解决方法是将state属性传递到链接中,如<Link to={{pathname: "/page", state: "desiredState"}}>Page</Link>。然后我可以在目标组件(例如<Page />)的componentWillReceiveProps函数中检查:

componentWillReceiveProps(nextProps){
  if (nextProps.location.state === 'desiredState') {
    // do stuffs
  }
}

第二个问题:

 

在React Router v4文档中的奇怪箭头函数...我找不到任何关于普通括号而不是圆括号的内容。它们是什么?

箭头函数;@Dennis和@Jaromanda X已经谈到了。然而,我有三点要补充:

  • 当你有() => blah而没有花括号{}时,你隐式返回紧跟着=>之后的东西,在这种情况下是blah。但是,当你在箭头后面立即加上花括号时,现在你需要负责如果需要的话return一些东西。因此,() => blah(顺便说一下,与() => (blah)同义)将更类似于() => { return blah },而不是() => { blah }
  • 那么如果你想返回一个对象:{ blah: blah };这就是@Jaromanda X指出的。你需要这样做:() => ({ blah: blah })或者简单地() => ({ blah })进行隐式返回,或者你可以显式地这样返回:() => { return { blah: blah } }
  • 我的第三个要点是指向MDN

希望能对你有所帮助。


在我的情况下,我遇到了与react-router相同的问题,它确实更改了URL但没有更改页面内容。在我尝试了你的解决方案之后,它仍然不起作用。有什么建议吗? - amrs-tech
@amrs-tech 如果没有看到你路由相关的代码,建议会很棘手。不过,你可以尝试这个猜测,将React Router的render改为使用component属性。也就是说,如果你使用了<Route render={() => <YourComponent />} />,那么尝试改为<Route component={YourComponent} />。¯_(ツ)_/¯ 祝好运! - flash
在 React Hooks 中,我遇到了 <Link href=""> 的问题。页面无法完全加载,但是使用 <a href=""> 可以。 - Alejandro H

21

href属性会触发页面刷新,从而重置应用程序状态。然而,react-router的链接和导航链接不会触发页面刷新。由于React通常用于创建单页应用程序,请确保在处理路由时选择Link或Navlink。


3

看源代码是最好的方式。

https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/Link.js

你可以看到,Link 是一个组件,内部使用 history。这是 react-router 的历史和导航背后的模块|库,并带有不同的模式(内存历史记录、浏览器历史记录、哈希历史记录。甚至是自定义的)。

是的,类似地,它呈现了一个锚标记,但默认行为被覆盖了(preventDefault())。他们本可以使用一个 div,但并不完全正确。原因如下。

所以基本上它的工作原理是这样的:

观察下面的条件

  if (
          !event.defaultPrevented && // onClick prevented default
          event.button === 0 && // ignore everything but left clicks
          (!this.props.target || this.props.target === "_self") && // let browser handle "target=_blank" etc.
          !isModifiedEvent(event) // ignore clicks with modifier keys
    ) {

}

如果条件符合,则使用history(推送或替换)。否则,它将保留浏览器正常行为。在这种情况下,它将只是一个普通的锚标签<a />。例如,让浏览器处理target='blank'。这些条件已经很好地解释了。
然后,根据历史对象的类型,行为会发生改变。不是``本身的行为。而仅仅是历史对象类型的结果。
总之:<Link />是一个组件,用于呈现<a />锚标签。但在主要条件下,默认行为被阻止(preventDefault())。这使得它能够应用于历史对象的更改(onClick事件)。而在某些情况下,如上所述,它会回退到浏览器行为。并且恰好就是一个<a />锚标签(没有preventDefault())。
对于使用方法,如果您正在使用React-router,那么只需要使用Link即可。

3

组件允许您比普通的链接元素做更多的事情。例如,因为它是一个React组件,您可以享受到具有状态等好处(如果您需要)。您可以在此处查看更多文档。没有错误,我不确定会发生什么,但我怀疑路由库希望您使用组件而不是普通的HTML元素。

关于() => {},这是一种称为匿名函数或lambda表达式的构造。它基本上与将函数保存在变量中相同:var x = function(){ return (<div>...) }; 如果第一个括号中有任何内容,则是您可以访问的参数:const x = (y) => return y*2; 在React中执行此操作的原因是将函数范围暴露给其所在的组件。


嗨,我已经编辑了以显示错误和我的类。你认为你知道问题是什么吗? - forJ
只要你不使用任何其他奇怪的东西,我就不是完全确定。 <Link to="/something">链接</Link> 将 URI 更改为 /something,然后您的 <Route path="/something" component={Something} /> 应该会注意到并呈现任何 <Something />。你说它可以用 <a>,这是否意味着正确的组件被呈现了?您可以尝试将您的代码与此代码进行比较,此代码有效。 https://fiddle.jshell.net/terda12/mana88Lm/ - Dennis
据我所知,RouteHandler在React Route v4中已被弃用,在v4中,似乎我们必须直接将路由放在子类中。我参考了这个页面https://reacttraining.com/react-router/web/example/basic - forJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接