react-router-dom 5.X

安装

npm install --save react-router-dom

使用

导入

import { BrowserRouter as Router, Route, Link } from "react-router-dom";
上述import是es6语法,其中as是取别名用的

简单实例

import React from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Home from './components/Home'
import News from './components/News'
import Music from './components/Music'

function App() {
  return (
    
      {/* exact准确匹配 */}
      
      
    
  );
}

export default App;

注意,每个路由必须被外层的Router包裹
exact的存在是严格匹配,去掉的话,访问/news实际会渲染Home

Link的使用

类似vue的vue-router,实际每个Link默认被渲染为a标签

首页
新闻
音乐

react-router-dom 官方示例解读

BasicExample–基础实例

这是一个最基础的路由示例,根据不同的url渲染不同的组件。值得注意的是,对于Route组件而言,支持的渲染组件方式不唯一单标签的时候可以使用component属性,render属性,或者children属性挂载要渲染的组件。双标签的时候包裹要渲染的组件,也就是children…

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

const Home = () => 

Home

const About = () =>

About

const Dashboard = () =>

Dashboard

const News = () =>

News

const Games = () =>

Games

export default function () { return (
  • Home
  • About
  • Dashboard
  • News
  • Games

} /> } /> } />
); }

UrlParams–动态路由

 该示例演示了动态路由是如何匹配的,以及如何获取匹配到的参数值。和很多框架匹配规则一致,都是:param.在获取参数的时候,可以用hooks形式 ,也可以用原始的props.match.params.xxx

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


export default function () {
    return (
        
            

Accounts

  • Netflix
  • Zillow Group
  • Yahoo
  • Modus Create
); } function Child(props) { let { page} = useParams(); let num=props.match.params.num; return (

当前页: {page}--数字:{num}

); }

Nesting–嵌套路由

 嵌套路由适用于有明显层级划分的情况,以官方示例来看,主层级分为home和topics,topics又划分出三个子主题,这就涉及到了嵌套路由。子路由的url都是在父级路由基础上拼接出来的。像这样 /topics /topics/rendering。值得注意的是,这个案例里用到了一个新的hooks,useRouteMatch,这就相当于原始的props.match.此外,这个示例里对useRouteMatch()解构了path和url,如果你打印一下,你会发现它们的值是一样的,也许就像原文解释那样,一个用来获取父路径,一个用于Link组件的跳转,更规范?

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

const Home = () => 

Home

const Topic = () => { let { topicId } = useParams(); return

{topicId}

} const Topics = () => { let { path, url } = useRouteMatch(); return (

Topics

  • Rendering with React
  • Components
  • Props v. State

Please select a topic.

); } export default function () { return (
  • Home
  • Topics

); }

react-router-dom 5.X_第1张图片

 

 

 

AuthRoute–路由鉴权

这个demo.核心是通过高阶组件+状态控制实现路由鉴权。在实际开发中,有些页面必须登录才可以访问,甚至不同身份的人看到的页面也是不一样的。public页面都可以访问,protected页面必须登录才可以访问。登录状态这里使用一个变量isLogin控制.Redirect 组件用于身份验证不通过时重定向处理,useHistory 钩子函数可获取历史记录接口,控制页面跳转。PrivateRoute 是一个高阶组件,对基础的Route进行了进一步封装,注意...rest,在这里相当于将高阶组件获取的path属性传递给Route

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

let isLogin = false;

const LoginBtn = () =>   

const LoginOutBtn = () => {
  let history=useHistory();
  return 
}

const Login = () => 
const Condition = ({ children }) => isLogin ? children :

const PrivateRoute = ({ children, ...rest }) => { return ( } /> ); } export default function () { return (

public

protected

home

} />

public

} />

已经登录 可查看-protected

) }

CustomLink–自定义路由 

自定义路由本质是在Route组件的基础上加入了一些定制化处理,相当于包裹了一层。为了更好理解,这里对官方示例做了个微调,强匹配属性exact直接写入而不是传参形式体现。useRouteMatch可以根据path返回一个匹配结果对象,exact表示强匹配
,借助于Route组件,useRouteMatch可以空调用,像这样useRouteMatch().反之,需要传参。可嵌套路由,对比查看。

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


const Home = () => 

Home

const About = () =>

About

export default function () { return (

); } function MyLink({ label, to }) { let match = useRouteMatch({ path: to, exact: true }) // 这里返回的match对象仅用于样式控制 return (
{match && "> "} {label}
); }

PreventingTransitions–阻止过渡

正常情况下,在用户在表单中填写了一些信息但是没提交的情况下,点击其他页面跳转链接,等再返回的时候,表单数据会丢失。这个例子就是提供一种阻断方式,在进行页面跳转的时候给用户一个提示,确认后会跳转,避免因为误操作导致的表单数据丢失。提示这里使用的是Prompt组件,when属性为一个布尔值,true弹出提示框,message为具体的提示信息。Prompt也可以写在form之外,保证在要渲染的组件里即可。这种场景,通常用于长表单输入,比如注册。关于Prompt,还有个好用的点,下边单独介绍。

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

// Sometimes you want to prevent the user from
// navigating away from a page. The most common
// use case is when they have entered some data
// into a form but haven't submitted it yet, and
// you don't want them to lose it.

export default function PreventingTransitionsExample() {
  return (
    
      
  • Form
  • One
  • Two
} /> One} /> Two} />
); } function BlockingForm() { let [isBlocking, setIsBlocking] = useState(false); return ( <form onSubmit={event => { event.preventDefault(); event.target.reset(); setIsBlocking(false); }} > <Prompt when={isBlocking} message={location => `Are you sure you want to go to ${location.pathname}` } />

Blocking?{" "} {isBlocking ? "Yes, click a link or the back button" : "Nope"}

<input size="50" placeholder="type something to block transitions" onChange={event => { setIsBlocking(event.target.value.length > 0); }} />

); }

Prompt

  • message属性还可以接收一个函数,该函数可以获取到下一个位置(location),返回true不提示,反之,弹出提示
<Prompt message={location =>
          location.pathname.startsWith("/one")
            ? true
            : `Are you sure you want to go to ${location.pathname}?`
        }
      />

NO Match–404

 该示例演示的是对404的处理,用于捕获所有未匹配的项,通常放置于Switch的最后一项Route里,匹配规则为*。当然,也许你还想将所有的未捕获页面都跳转到/error,这个需要使用重定向,后边会介绍

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



export default function NoMatchExample() {
  return (
    
      
  • Home
  • Old Match, to be redirected
  • Will Match
  • Will Not Match
  • Also Will Not Match
); } function Home() { return

Home

; } function WillMatch() { return

Matched!

; } function NoMatch() { let location = useLocation(); return (

No match for {location.pathname}

); }

统一处理404

 
  
  
  
  

Sidebar 侧边栏

侧边栏这个案例很常见,官方示例里边介绍的除了基础侧边栏,还扩展了一种多处渲染的方式。即当路由匹配到当前url时,可以在应用给程序内任何你想渲染的地方去分别渲染sideber和main,注意下边的map遍历,只有children属性那里有差异

import React from "react";

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


const routes = [
  {
    path: "/",
    exact: true,
    sidebar: () => 
home!
, main: () =>

Home

}, { path: "/bubblegum", sidebar: () =>
bubblegum!
, main: () =>

Bubblegum

}, { path: "/shoelaces", sidebar: () =>
shoelaces!
, main: () =>

Shoelaces

} ]; export default function SidebarExample() { return (
<div style={{ padding: "10px", width: "40%", background: "#f0f0f0" }} >
  • Home
  • Bubblegum
  • Shoelaces
{routes.map((route, index) => ( <Route key={index} path={route.path} exact={route.exact} children={} /> ))}
{routes.map((route, index) => ( <Route key={index} path={route.path} exact={route.exact} children={} /> ))}
); }
render(
,document.getElementById("root"))
  • 结合效果图来看,侧边栏底部和右侧,都进行了渲染,即多处渲染。注意,这两次其实除了渲染的组件不同,其他都一样

config 路由配置

 有时候,也许你希望将路由集中配置,比如放在一个数组里,每个路由对象包含path和component。涉及嵌套的,就再来一个数组,存放子路由对象。

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


const Sandwiches = () => 

Sandwiches

const Bus = () =>

Bus

const Cart = () =>

Cart

const routes = [ { path: "/sandwiches", component: Sandwiches }, { path: "/tacos", component: Tacos, routes: [ { path: "/tacos/bus", component: Bus }, { path: "/tacos/cart", component: Cart } ] } ]; export default function App() { return (
  • Tacos
  • Sandwiches
{routes.map((route, i) => ( ))}
); } function RouteWithSubRoutes(route) { return ( <Route path={route.path} render={(props) => { return }} /> ); } function Tacos({ routes }) { return (

Tacos

  • Bus
  • Cart
{routes.map((route, i) => ( ))}
); } render(, document.getElementById("root"))

Query parameters 查询参数

 该示例其实本质是借用了浏览器内置的URLSearchParams,这个方法可以很方便的解析url参数,但这个存在兼容问题,放弃IE家族就没问题了。具体URLSearchParamsAPI,可参考MDN这段示例代码:

var paramsString = "q=URLUtils.searchParams&topic=api"
var searchParams = new URLSearchParams(paramsString);

searchParams.has("topic") === true; // true
searchParams.get("topic") === "api"; // true
searchParams.getAll("topic"); // ["api"]
searchParams.get("foo") === null; // true
searchParams.append("topic", "webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"
searchParams.set("topic", "More webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev"
searchParams.delete("topic");
searchParams.toString(); // "q=URLUtils.searchParams"
import React from "react";
import { render } from 'react-dom'
import {
  BrowserRouter as Router,
  Link,
  useLocation
} from "react-router-dom";



export default function App() {
  return (
    
      
    
  );
}

//这里是重点
function useQuery() {
  return new URLSearchParams(useLocation().search);
}

function QueryParamsDemo() {
  let query = useQuery();
  return (
    

Accounts

  • Netflix
  • Zillow Group
  • Yahoo
  • Modus Create
); } function Child({ name }) { return (
{name ? (

The name in the query string is "{name} &quot;

) : (

There is no name in the query string

)}
); }
render(
, document.getElementById("root"))

 

 

你可能感兴趣的:(react-router-dom 5.X)