关于javascript:React-系列十二React-Router

2次阅读

共计 8126 个字符,预计需要花费 21 分钟才能阅读完成。

快来退出咱们吧!

“ 小和山的菜鸟们 ”,为前端开发者提供技术相干资讯以及系列根底文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 (https://xhs-rookies.com/) 进行学习,及时获取最新文章。

“Code tailor”,如果您对咱们文章感兴趣、或是想提一些倡议,微信关注 “小和山的菜鸟们” 公众号,与咱们取的分割,您也能够在微信上观看咱们的文章。每一个倡议或是同意都是对咱们极大的激励

前言

这节咱们将介绍 Reactreact - router,路由跳转的配置以及应用

本文会向你介绍以下内容:

  • 意识 react-router
  • react-router 根本应用
  • react-router 高级应用
  • react-router-config

意识 react – router

如果你是第一次接触 router 这个名词,能够先去这里补充一下本人的路由常识再来往下浏览哦

留神:以下内容基于 react-router v5 版本,如果和读者以后应用的不合乎,请以官网为主

装置 react-router

yarn add react-router-dom

npm install react-router-dom

什么是 react-router

React Router is a set of navigation components that are combined with your application in a declarative manner. Whether you want to provide bookmarkable URLs for your web applications or use composable navigation methods in React Native, React Router can be used anywhere React renders

react-router 是一组以申明形式与您的应用程序组合的导航组件,换句话,react-routerReact 体系中的路由库,它通过治理 URL,实现组件的切换和状态的变动

react-router 根本应用

React Router 中的组件次要分为三类:

路由器 BrowserRouterHashRouter

  • BrowserRouter 应用惯例 URL 门路,创立一个像 example.com/some/path 这样实在的 URL,然而他们要求正确的配置服务器
  • HashRouter 将以后地位存储在 URL 的哈希局部中,因而 URL 看起来相似于http://example.com/#/your/page,因为哈希从不发送到服务器,因而这意味着不须要非凡的服务器配置

两者之间的次要区别是它们存储 URL 和与 Web 服务器通信的形式

路由匹配器,例如 Switch 和 Route:

当渲染 Switch 组件时,它将搜寻它的 Route 子元素,以查找门路与以后 URL 匹配的元素,它将出现找到的第一个 Route 并疏忽所有的其余路由。这意味着您应该将蕴含更多特定门路的 Route 放在不那么特定的路由之前

Switch

咱们来看上面的路由规定:

  • 当咱们匹配到某一个门路时,咱们会发现有一些问题;
  • 比方 /about 门路匹配到的同时,/:userid 也被匹配到了,并且最初的一个 NoMatch 组件总是被匹配到;
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
<Route path="/:userid" component={User}/>
<Route component={NoMatch}/>

起因是什么呢?默认状况下,react-router 中只有是门路被匹配到的 Route 对应的组件都会被渲染;

然而理论开发中,咱们往往心愿有一种排他的思维:

  • 只有匹配到了第一个,那么前面的就不应该持续匹配了;
  • 这个时候咱们能够应用 Switch 来将所有的 Route 进行包裹即可;
<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/about" component={About} />
  <Route path="/profile" component={Profile} />
  <Route path="/:userid" component={User} />
  <Route component={NoMatch} />
</Switch>

Route

它最根本的职责是在其门路与以后 URL 匹配时出现一些 UI

Route 的渲染办法一共有三类

  • <Route component>
  • <Route render>
  • <Route children>

Route component

仅在地位匹配时依据 route props 渲染

import React from "react";
import ReactDOM from "react-dom";
import {BrowserRouter as Router, Route} from "react-router-dom";

// All route props (match, location and history) are available to User
function User(props) {return <h1>Hello {props.match.params.username}!</h1>;
}

ReactDOM.render(
  <Router>
    <Route path="/user/:username" component={User} />
  </Router>,
  node
);

当你在应用此办法加载时,router 通常会依据给定的 component 去调用 React.createElement 创立一个新的 React 元素。这也就意味着如果你在此是用内联函数渲染的组件,那么它将会在每次渲染时都创立一个新的函数,即卸载组件装置新有组件,而不是更新。所以当你应用内联函数渲染组件时,请抉择 renderchildren 办法

Route render

你能够传入一个在地位匹配时调用的函数,而不是应用组件 prop 为您创立一个新的 React 元素

import React from "react";
import ReactDOM from "react-dom";
import {BrowserRouter as Router, Route} from "react-router-dom";

// convenient inline rendering
ReactDOM.render(
  <Router>
    <Route path="/home" render={() => <div>Home</div>} />
  </Router>,
  node
);

// wrapping/composing
// You can spread routeProps to make them available to your rendered Component
function FadingRoute({component: Component, ...rest}) {
  return (
    <Route
      {...rest}
      render={routeProps => (
        <FadeIn>
          <Component {...routeProps} />
        </FadeIn>
      )}
    />
  );
}

ReactDOM.render(
  <Router>
    <FadingRoute path="/cool" component={Something} />
  </Router>,
  node
);

须要留神的是:<Route component> 的优先级比 <Route render> 高,所以不要在同一个 Route 中同时调用两种办法

Route children

工作原理同 <Route render>,只是无论是否匹配都会调用

import React from "react";
import ReactDOM from "react-dom";
import {
  BrowserRouter as Router,
  Link,
  Route
} from "react-router-dom";

function ListItemLink({to, ...rest}) {
  return (
    <Route
      path={to}
      children={({match}) => (<li className={match ? "active" : ""}>
          <Link to={to} {...rest} />
        </li>
      )}
    />
  );
}

ReactDOM.render(
  <Router>
    <ul>
      <ListItemLink to="/somewhere" />
      <ListItemLink to="/somewhere-else" />
    </ul>
  </Router>,
  node
);

须要留神的是:<React children> 优先级比下面两个优先级都高

而这三种渲染形式都会传递雷同的 route props

  • match:蕴含 <Route path> 如何匹配 URL 的信息
  • location:代表应用程序当初所在的地位
  • history:用于在 JavaScript 中以各种形式治理会话历史记录

路由导航,例如:Link、NavLink、Redirect

  • <Link> 组件将在您的应用程序中创立链接。无论在何处出现 <Link>,锚点都将出现在 HTML 文档中,而其最终会被渲染成 a 元素
  • NavLinkLink 根底之上减少了一些款式属性,当其 prop 与以后地位匹配时,能够给它设置一个 activeClassName(被选中)的款式。
  • 任何时候要强制导航,你都能够应用 <Redirect>,当出现 <Redirect> 时,将依据 propto 值进行导航。
NavLink

门路选中时,对应的 a 元素变为红色

  • activeStyle:沉闷时(匹配时)的款式;
  • activeClassName:沉闷时增加的 class;
  • exact:是否精准匹配;
<NavLink to="/" activeStyle={{color: "red"}}>home</NavLink>
<NavLink to="/about" activeStyle={{color: "red"}}>about</NavLink>
<NavLink to="/profile" activeStyle={{color: "red"}}>profile</NavLink>

然而,咱们会发现在选中 aboutprofile 时,第一个也会变成红色:

  • 起因是 / 门路也匹配到了 /about/profile
  • 这个时候,咱们能够在第一个 NavLink 中增加上 exact 属性
<NavLink exact to="/" activeStyle={{color: 'red'}}>
  home
</NavLink>

默认的 activeClassName

  • 事实上在默认匹配胜利时,NavLink 就会增加上一个动静的 active class
  • 所以咱们也能够间接编写款式
a.active {color: red;}

当然,如果你放心这个 class 在其余中央被应用了,呈现款式的层叠,也能够自定义 class

<NavLink exact to="/" activeClassName="link-active">home</NavLink>
<NavLink to="/about" activeClassName="link-active">about</NavLink>
<NavLink to="/profile" activeClassName="link-active">profile</NavLink>
Redirect

Redirect 用于路由的重定向,当这个组件呈现时,就会执行跳转到对应的 to 门路中,而 Redirect 最常见的场景即鉴权

  • 用户浏览器输出 User 界面 url
  • 若用户未登录,需重定向到登录页面。若已登录,则可进入 User 界面

App.js 中提前定义好 Login 页面对应的 Route

<Switch>
  ... 其余 Route
  <Route path="/login" component={Login} />
  <Route component={NoMatch} />
</Switch>

User.js 中写上对应的逻辑代码:

import React, {PureComponent} from 'react'
import {Redirect} from 'react-router-dom'

export default class User extends PureComponent {constructor(props) {super(props)

    this.state = {isLogin: false,}
  }

  render() {
    return this.state.isLogin ? (
      <div>
        <h2> 微信公众号:小和山的菜鸟们 </h2>
        <h2> 用户名: Coder tailor</h2>
      </div>
    ) : (<Redirect to="/login" />)
  }
}

react-router 高级应用

嵌套路由

此示例显示嵌套路由的工作原理。路由 /topics 加载 Topics 组件,该组件依据门路 :id 值有条件地出现任何进一步的 <Route>

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  useRouteMatch,
  useParams
} from "react-router-dom";

export default function App() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/topics">Topics</Link>
          </li>
        </ul>

        <Switch>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/topics">
            <Topics />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {return <h2>Home</h2>;}

function About() {return <h2>About</h2>;}

function Topics() {let match = useRouteMatch();

  return (
    <div>
      <h2>Topics</h2>

      <ul>
        <li>
          <Link to={`${match.url}/components`}>Components</Link>
        </li>
        <li>
          <Link to={`${match.url}/props-v-state`}>
            Props v. State
          </Link>
        </li>
      </ul>

      {/* Topics 页面有本人的 <Switch>,其中蕴含更多基于 /topics URL 门路
          的路由。您能够将此处的第二个 <Route> 视为所有主题的“索引”页面,或者
          未抉择主题时显示的页面 */}
      
      <Switch>
        <Route path={`${match.path}/:topicId`}>
          <Topic />
        </Route>
        <Route path={match.path}>
          <h3>Please select a topic.</h3>
        </Route>
      </Switch>
    </div>
  );
}

function Topic() {let { topicId} = useParams();
  return <h3>Requested topic ID: {topicId}</h3>;
}

动静路由

当咱们探讨动静路由时,咱们是指在您的利用渲染时产生的路由,而不是在运行中的利用之外配置或约定的。

这意味着简直所有内容都是 React Router 中的一个组件。上面是对该 API 的回顾,以理解其工作原理:

首先,为您要定位的环境获取一个 Router 组件,并将其出现在应用程序的顶部。

// react-dom (what we'll use here)
import {BrowserRouter} from "react-router-dom";

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

const App = () => (
  <div>
    <nav>
      <Link to="/dashboard">Dashboard</Link>
    </nav>
    <div>
      <Route path="/dashboard" component={Dashboard} />
    </div>
  </div>
);

Route 将出现 <Dashboard {... props} />,其中 props 是路由器特定的货色,比方 {match, location, history}。如果用户不在 / dashboard 上,则 Route 将出现 null

react-router-config

路由配置的形式多种多样,让咱们看一下来自官网的最佳实际

// 路由配置只是数据
// React 十分善于将数据映射到组件中,而 <Route> 是一个组件.

// 咱们的路由配置只是一个带有 path 和 component props 的逻辑 "路由" 数组
// 排序形式与你在 `<Switch>` 中的程序雷同。// 路由配置
const routes = [
  {
    path: "/sandwiches",
    component: Sandwiches
  },
  {
    path: "/tacos",
    component: Tacos,
    routes: [
      {
        path: "/tacos/bus",
        component: Bus
      },
      {
        path: "/tacos/cart",
        component: Cart
      }
    ]
  }
];

嵌入 App 中

export default function App() {
  ReactDOM.render(
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/tacos">Tacos</Link>
          </li>
          <li>
            <Link to="/sandwiches">Sandwiches</Link>
          </li>
        </ul>

        <Switch>
          {routes.map((route, i) => (<RouteWithSubRoutes key={i} {...route} />
          ))}
        </Switch>
      </div>
    </Router>
  ,document.getElementById('root')
  )
}

组件在这儿

function Sandwiches() {return <h2>Sandwiches</h2>;}

function Tacos({routes}) {
  return (
    <div>
      <h2>Tacos</h2>
      <ul>
        <li>
          <Link to="/tacos/bus">Bus</Link>
        </li>
        <li>
          <Link to="/tacos/cart">Cart</Link>
        </li>
      </ul>

      <Switch>
        {routes.map((route, i) => (<RouteWithSubRoutes key={i} {...route} />
        ))}
      </Switch>
    </div>
  );
}

function Bus() {return <h3>Bus</h3>;}

function Cart() {return <h3>Cart</h3>;}

//<Route> 的非凡包装器,它晓得如何通过将 "子" 路由
// 传递到它出现的组件的 `routes` 属性来解决它们。function RouteWithSubRoutes(route) {
  return (
    <Route
      path={route.path}
      render={props => (
        // pass the sub-routes down to keep nesting
        <route.component {...props} routes={route.routes} />
      )}
    />
  );
}

下节预报

本节咱们学习了 React-Router 中高阶组件以及组件补充的内容,至此,React 相干常识咱们已学习结束,下一节咱们将为之前的留言板加上登录性能!

正文完
 0