ReactJS Bootstrap 导航栏和路由不能一起工作

Posted

技术标签:

【中文标题】ReactJS Bootstrap 导航栏和路由不能一起工作【英文标题】:ReactJS Bootstrap Navbar and Routing not working together 【发布时间】:2019-07-17 12:07:28 【问题描述】:

我正在尝试使用 ReactJS 创建一个简单的 Webapp,并且我想使用 React-Bootstrap 提供的 Navbar

我创建了一个Navigation.js 文件,其中包含一个Navigation 类,以将Navbar 和路由与App.js 文件分开。但是,这两个部分似乎都不起作用。当我加载页面时,它只是空的,没有导航栏。谁能发现错误?

导航.js:

import React,  Component  from 'react';
import  Navbar, Nav, Form, FormControl, Button, NavItem  from 'react-bootstrap';
import  Switch, Route  from 'react-router-dom';
import  Home  from './Page';

class Navigation extends Component 
    render() 
        return (
            <div>
                <div>
                    <Navbar>
                        <Navbar.Brand href="/">React-Bootstrap</Navbar.Brand>
                        <Navbar.Collapse>
                            <Nav className="mr-auto">
                                <NavItem eventkey=1 href="/">
                                    <Nav.Link href="/">Home</Nav.Link>
                                </NavItem>
                            </Nav>
                            <Form inline>
                                <FormControl type="text" placeholder="Search" className="mr-sm-2" />
                                <Button variant="outline-success">Search</Button>
                            </Form>
                        </Navbar.Collapse>
                    </Navbar>
                </div>
                <div>
                    <Switch>
                        <Route exact path='/' component=Home />
                        <Route render=function () 
                            return <p>Not found</p>
                         />
                    </Switch>
                </div>
            </div>
        );
    


export default Navigation;

App.js:

import React,  Component  from 'react';
import Navigation from './components/routing/Navigation';



class App extends Component 
  render() 
    return (
      <div id="App">
        <Navigation />
      </div>
    );
  


export default App;

我尝试使用包含来自react-router-bootstrapLinkContainerNavItem,这导致了相同的结果。

为了完整性,Page.js:

import React,  Component  from 'react';
import  Link  from 'react-router-dom';

export const Page = ( title ) => (
    <div className="App">
      <div className="App-header">
        <h2>title</h2>
      </div>
      <p className="App-intro">
        This is the title page.
      </p>
      <p>
        <Link to="/">Home</Link>
      </p>
      <p>
        <Link to="/about">About</Link>
      </p>
      <p>
        <Link to="/settings">Settings</Link>
      </p>
    </div>
);


export const About = (props) => (
    <Page title="About"/>
);

export  const Settings = (props) => (
    <Page title="Settings"/>
);

export const Home = (props) => (
    <Page title="Home"/>
);

【问题讨论】:

【参考方案1】:

首先,在您的 sn-ps 中,您似乎没有将代码包装在 Router 中,因此您应该确保在 AppReactDOM.render 中执行此操作:

import  BrowserRouter  from 'react-router-dom';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>, 
  rootElement
  );

接下来,您的具体问题是您正在渲染 react-bootstrap 的 Nav.Link 而不是 react-router 的 Link 组件,因此路由器不会接收您的路由更改。幸运的是,react-bootstrap 在它的大部分组件中都提供了一个 render prop 来指定如果你不想使用默认值,你想要渲染哪个组件或元素。切换到这样的东西:

import  Switch, Route, Link  from 'react-router-dom';

class Navigation extends Component 
  render() 
    return (
      <div>
        <div>
          <Navbar>
            <Navbar.Brand as=Link to="/" >React-Bootstrap</Navbar.Brand>
            <Navbar.Collapse>
              <Nav className="mr-auto">
                <NavItem eventkey=1 href="/">
                  <Nav.Link as=Link to="/" >Home</Nav.Link>
                </NavItem>
              </Nav>
              <Form inline>
                <FormControl type="text" placeholder="Search" className="mr-sm-2" />
                <Button variant="outline-success">Search</Button>
              </Form>
            </Navbar.Collapse>
          </Navbar>
        </div>
        <div>
          <Switch>
            <Route exact path='/' component=Home />
            <Route render=function () 
              return <p>Not found</p>
             />
          </Switch>
        </div>
      </div>
    );
  

【讨论】:

谢谢先生! as=Link 和 to"..." 是我所缺少的。奇怪的是引导文档根本没有提到这一点。 看起来应该有Nav.Item而不是NavItem @kugo2006 它们是相同的组件,但是是的,它与Nav.Item 相比少了一个导入。另外,问题是关于Nav.Link 和路由器的,看起来我只是从 OP 的问题中复制了 sn-p 并修复了它,所以我没有做很多重构:) 我想知道在文档中哪里可以找到它。请有人将链接粘贴到提到的文档中以供参考。我们怎么知道有 'as' 属性? @GeorgiGeorgiev react-bootstrap.github.io/components/navs/#nav-link-props【参考方案2】:

对于那些在 react-bootstrap 导航栏中对 react-router-dom 中的 Link 组件样式有问题的人,只需添加 className="nav-link",如下所示:

&lt;Link to="/" className="nav-link"&gt;Home&lt;/Link&gt;

而不是

&lt;Nav.Link href="/"&gt;Home&lt;/Nav.Link&gt;

【讨论】:

我也遇到了同样的问题,但我认为最好改用这个:&lt;Nav.Link as=Link href="/"&gt;Home&lt;/Nav.Link&gt; 其中Link 是来自react-router-dom 的组件。 @MatíasP。如果使用as=Link,则必须将href 替换为to 谢谢。这些答案正是我正在寻找的 &lt;Link to="/" className="nav-link"&gt;Home&lt;/Link&gt;&lt;Nav.Link as=Link to="/" &gt;Home&lt;/Nav.Link&gt;【参考方案3】:

我希望我能帮助其他试图解决这个问题的人为时不晚。

您可以使用 NavLink,而不是 as=Link。它将以与 Link 相同的行为呈现,但会“监视”路由器 URL 以定义哪个链接确实处于活动状态:

<Nav defaultActiveKey="/bills" as="ul">
      <Nav.Item as="li">
        <Nav.Link as=NavLink to="/bills">Dividas</Nav.Link>
      </Nav.Item>
      <Nav.Item as="li">
        <Nav.Link as=NavLink to="/other">Em construção</Nav.Link>
      </Nav.Item>
    </Nav>

【讨论】:

【参考方案4】:
import ReactDOM from 'react-dom';
import  BrowserRouter  from 'react-router-dom';

ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);

和 Navbar.js:

import React from 'react';
import Container,Navbar,Nav,NavItem  from 'react-bootstrap';
import Link from 'react-router-dom';

<Nav className="ml-auto">
<NavItem>   <Link className="nav-link"   to="/">Home</Link> </NavItem> 
<NavItem>   <Link  className="nav-link" to="/about">About</Link> </NavItem> 
<NavItem>    <Link className="nav-link"   to="/contact">Contact</Link> </NavItem> 
</Nav>

这解决了我的&lt;Link&gt; 外部&lt;Router&gt; 错误。

【讨论】:

【参考方案5】:

发现自己有一个不平凡的项目,并且已经将 jQuery 作为依赖项,我能够优雅地解决 react-router / react-bootstrap 与 document 上的事件侦听器不匹配的问题。

与其他解决方案相比,这具有一个优势,即无需更改当前标记。但是,根据需要,可能需要编写一些额外的逻辑来保护history.push 调用。可能还需要扩展它以保护target 属性,例如target="_blank".

如果不需要 jQuery,可以使用document.addEventListener 编写一个普通的 JS 实现,而不需要太多额外的努力。

// react-router@5
// usage of history may vary depending on version
import  Router  from 'react-router-dom';
import  createBrowserHistory  from 'history';

const history = createBrowserHistory();

// IIFE scoping jQuery for us
(($) => 
  // Wait for document ready
  $(() => 
    $(document).on('click', '[href]', (event) => 
      // Only target links targeting our application's origin
      if (event.currentTarget.href.indexOf(window.location.origin) === 0) 
        // Prevent standard browser navigation
        event.preventDefault();

        const path = event.currentTarget.href.slice(window.location.origin.length);

        history.push(path);
      
    );
  );
)(jQuery);

const Routing = (props) => (
  <Router history= history >
    ...
  </Router>
);

【讨论】:

【参考方案6】:

我认为您忘记包含引导 css,请参阅以下文档的样式表部分

https://react-bootstrap.github.io/getting-started/introduction/

或者只是将以下内容添加到您的 index.html

<link
  rel="stylesheet"
  href="https://maxcdn.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
  integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
  crossorigin="anonymous"
/>

【讨论】:

我已经在 index.js 中包含了引导 css,无论如何感谢您的回答。 跟css没什么关系,就是react router

以上是关于ReactJS Bootstrap 导航栏和路由不能一起工作的主要内容,如果未能解决你的问题,请参考以下文章

Bootstrap 4 导航栏和内容填充高度 flexbox

导航栏和粘性 Bootstrap 页脚之间的 100% 高度

导航栏和图像显示之间的线

前端学习(3026):vue+element今日头条管理-让导航栏和路由对应起来

element-admin,首页为普通vue页面,不需要需要侧边栏和导航栏

在 ReactJS 中更改其他路由上的导航栏背景颜色