react-router-dom 简明教程

react-router-dom 简明教程
我们需要创建 react-pro 项目

create-react-app react-pro
cd react-pro
yarn add react-router-dom

我们看到的目录如下:

在 src 下新建一个 HelloRouter.js,代码如下:

import React, { PureComponent } from 'react';
import {BrowserRouter as Router,Switch,Route,Link
} from "react-router-dom";// 将路由拆分成数组的形式,有点像 vue 路由配置
const routes = [{to: '/',content: 'Home'},{to: '/about',content: 'About'},{to: '/users',content: 'Users'}
]// 创建组件的一种形式,变量的形式
const lis = routes.map((item, index) => {return (
  • {item.content}
  • ) })// 类组件的形式 class Home extends PureComponent {render() {return

    Home

    ;} }class About extends PureComponent {render() {return

    About

    ;} }class Users extends PureComponent {render() {return

    Users

    ;} }// 这里的 Switch Route 有点类似 js 中的 switch case 表示精准匹配 export default class HelloRouter extends PureComponent {render() {return ({/* A looks through its children s andrenders the first one that matches the current URL. */});} }

    效果如下:
    在这里插入图片描述
    嵌套路由

    接下来我们就来写写 react 的嵌套路由;
    首先我们在 src 下新建一个 QianTaoRouter.js,具体代码如下:

    import React, { PureComponent } from 'react';
    import {BrowserRouter as Router,Switch,Route,Link,useParams,useRouteMatch
    } from "react-router-dom";const routes = [{to: '/',content: 'Home'},{to: '/about',content: 'About'},{to: '/users',content: 'Users'},{to: '/topics',content: 'Topics'}
    ]const lis = routes.map((item, index) => {return (
  • {item.content}
  • ) })class Home extends PureComponent {render() {return

    Home

    ;} }class About extends PureComponent {render() {return

    About

    ;} }class Users extends PureComponent {render() {return

    Users

    ;} }function Topic() {let { topicId } = useParams();return

    Requested topic ID: {topicId}

    ; }function Topics() {let match = useRouteMatch();console.log("matach", match)return (

    Topics

    • Components
    • Props v. State
    {/* The Topics page has its own with more routesthat build on the /topics URL path. You can think of the2nd here as an "index" page for all topics, orthe page that is shown when no topic is selected */}

    Please select a topic.

    ); }export default class HelloRouter extends PureComponent {render() {return ({/* A looks through its children s andrenders the first one that matches the current URL. */});} }

    其中引人注意的是
    useRouteMatch 用于解析路由对象
    useParams 用于解析路由参数

    主要组件
    路由组件: BrowserRouter和HashRouter
    BrowserRouter使用浏览器的History API来管理url及与浏览器进行交互, 需要服务器增加配置以让所有的url请求返回同一个页面

    HashRouter将页面当前位置存储在url的hash部分(http://example.com/#/your/page.),不需要服务器增加特殊配置

    路由匹配组件Route和Switch
    Switch组件搜索其下路由Route组件,渲染第一个匹配到的路由而忽略其他 Route为视图渲染出口

    Please select a topic.

    导航组件Link,NavLink和Redirect
    Link组件用来在应用中创建链接。Link会被渲染成a标签

    • Components
    • Props v. State

    NavLink是一种特殊类型的Link,支持自动添加active class

    React
    // When the URL is /react, this renders:
    // React// When it's something else:
    // React
    

    任何时候你想强制导航,你可以渲染一个Redirect组件。当渲染时,它将使用其来支持导航

    
    

    代码分割
    即code-splitting, 网页的增量下载, 未使用到的包不会加载 我们使用webpack, @babel/plugin-syntax-dynamic-import, 和 loadable-components来实现代码分割 首先安装依赖包

    yarn add @babel/preset-react @babel/plugin-syntax-dynamic-import loadable-components --dev
    

    配置.babelrc文件(没有的话在项目根目录下新建一个)

    {"presets": ["@babel/preset-react"],"plugins": ["@babel/plugin-syntax-dynamic-import"]
    }
    

    修改App.js

    import React from "react";
    import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
    import loadable from "@loadable/component";
    import Loading from "../components/Loading";
    import "./App.css";const Counter = loadable(() => import("../features/counter/Counter"), {fallback: ,
    });
    const Book = loadable(() => import("../features/book/Book"), {fallback: ,
    });function App() {return ();
    }export default App;
    

    滚动状态恢复
    当路由切换时候页面自动滚动到顶部或者恢复滚动位置

    import { useEffect } from "react";
    import { useLocation } from "react-router-dom";export default function ScrollToTop() {const { pathname } = useLocation();useEffect(() => {window.scrollTo(0, 0);}, [pathname]);return null;
    }
    

    不使用Hook(v16.8以上才能够使用), 可以使用react-router-dom提供的withRouter高阶函数

    import React from "react";
    import { withRouter } from "react-router-dom";class ScrollToTop extends React.Component {componentDidUpdate(prevProps) {if (this.props.location.pathname !== prevProps.location.pathname) {window.scrollTo(0, 0);}}render() {return null;}
    }export default withRouter(ScrollToTop);
    

    重要API的适应
    BrowserRouter
    基于H5 History接口的路由

    forceRefresh={optionalBool}   getUserConfirmation={optionalFunc}keyLength={optionalNumber}   
    >
    
    

    Link
    声明式路由组件

    About
    
    {pathname: "/courses",    // 路径search: "?sort=name",  // 查询参数hash: "#the-hash",   // hash值state: { fromDashboard: true }  // 持久化到location的状态数据}}/>
    

    一个函数,当前位置作为参数传递给它,并且应该以字符串或对象的形式返回位置表示

     ({ ...location, pathname: "/courses" })} />
    
     `${location.pathname}?sort=name`} />
    

    其他可用属性

    replace: 当为true时,单击该链接将替换历史堆栈中的当前条目,而不是添加一个新条目。
    innerRef 值为函数

     {// node指向挂载的dom元素, 卸载时候为null}}
    />
    

    值为Ref对象

    let anchorRef = React.createRef()
    

    component 定制化自己的导航组件

    const FancyLink = React.forwardRef((props, ref) => (? {props.children}
    ))
    

    title, id, className等a标签接受的属性

    NavLink
    是 Link 的一个特殊版本,当呈现的元素与当前URL匹配时,它将向该元素添加样式属性。

    activeClassName 当元素处于active状态时,类将提供该class。默认的给定class是active。这将与className样式叠加

    activeStyle 内嵌方式声明active状态样式

    exact 布尔类型, 为true是路径完全匹配才会添加active class

    strict 路径匹配是否严格, 为true的话结尾的斜杠会被考虑

    isActive函数, 可以自定义active class添加逻辑

     {if (!match) {return false;}// only consider an event active if its event id is an odd numberconst eventID = parseInt(match.params.eventID);return !isNaN(eventID) && eventID % 2 === 1;}}
    >Event 123
    
    

    Redirect
    重定向

    {loggedIn ?  : }
    
    

    to也可以为对象

    {pathname: "/login",search: "?utm=your+face",state: { referrer: currentLocation }}}
    />
    

    push属性: 当为真时,重定向将把一个新的条目推送到历史中,而不是取代当前的条目。from属性: 要重定向的路径名。路径-regexp@^1.7.0能够理解的任何有效URL路径。在to中为模式提供了所有匹配的URL参数。必须包含to中使用的所有参数。不被to使用的其他参数将被忽略。

    
    // Redirect with matched parameters
    
    
    

    exact属性, 路径是否完全匹配

    strict属性:路径匹配是否严格,区分斜杠

    sensitive属性: 路径匹配是否大小写敏感

    Route
    路由组件可能是反应路由器中最重要的组件,了解和学习使用好。它最基本的职责是在路径与当前URL匹配时呈现某个UI

    route component
    只有路由匹配才会挂载component指定的组件

    ReactDOM.render(,node
    );
    

    render func
    路由匹配函数就会调用

    ReactDOM.render( Home} />,node
    );
    

    children func
    不管路由是否匹配都会渲染对应组件

    import React from "react";
    import ReactDOM from "react-dom";
    import {BrowserRouter as Router,Link,Route
    } from "react-router-dom";function ListItemLink({ to, ...rest }) {return ( (
  • )}/>); }ReactDOM.render(
    ,node );

    上面的例子中如果路径匹配的话会渲染带有active class的li 当添加动画过渡效果时候children属性也很有用

     ({/* Animate will always render, so you can use lifecyclesto animate its child in and out */}{match && })}
    />
    

    几个重要变量

    location
    {key: 'ac3df4', // not with HashHistory!pathname: '/somewhere',search: '?some=search-string',hash: '#howdy',state: {[userDefined]: true}
    }
    

    location会出现在下面几个地方

    Route component(路由组件)中使用 this.props.location
    Route组件的 render函数 as ({ location }) => ()
    Route组件的children属性 as ({ location }) => ()
    withRouter高阶函数包裹的组件中使用 as this.props.location
    match
    一个说明路由为何匹配的对象,包含路由跳转参数params, 是否精确匹配isExact, 路径path, url

    路由组件(Route component)中使用this.props.match
    路由render函数中解构出match对象Route render as ({ match }) => ()
    路由children函数中解构出match对象Route children as ({ match }) => ()
    withRouter高阶函数包裹组件中使用 this.props.match
    matchPath
    useRouteMatch
    可以基于此来实现路由嵌套

    import { Link, Switch, Route } from "react-router-dom";
    import { useRouteMatch } from "@/utils";
    export default function NestRoute() {const { path, url } = useRouteMatch("/demo");return (<>

    路由嵌套

    • demo1
    • demo2
    请选择一个实例

    {match.params.demoId}

    }>
    ); }

    history
    路由历史对象,包含以下属性

    length - (number) 历史堆栈中的条目数
    action - (string) 当前动作类型 (PUSH, REPLACE, or POP)
    location - (object) 当前的location对象,可能包含以下属性:
    pathname - (string) URL的path部分
    search - (string) URL的query部分
    hash - (string) URL hash部分
    state - (object)位置特定的状态,当此位置被推入堆栈时提供的推入状态(路径、状态)。仅在浏览器和内存历史中可用.
    push(path, [state]) - (function) 将新条目推入历史堆栈
    replace(path, [state]) - (function)替换历史堆栈上的当前条目
    go(n) - (function) 在历史堆栈中移动n(可正可负,即向前或者向后)个条目的指针
    goBack() - (function) 等价于go(-1), 后退一页
    goForward() - (function) 等价于 go(1), 前进一页
    历史对象是可变的。因此,建议从渲染道具中访问位置,而不是从history.location中访问

    常用Hooks
    react >= 16.8

    useHistory

    import { useHistory } from "react-router-dom";function HomeButton() {let history = useHistory();function handleClick() {history.push("/home");}return ();
    }
    

    useLocation
    获取位置对象

      let location = useLocation();
    useParams
    useParams返回一个包含URL参数的键/值对的对象。使用它来访问match。当前的参数。import React from "react";
    import ReactDOM from "react-dom";
    import {BrowserRouter as Router,Switch,Route,useParams
    } from "react-router-dom";function BlogPost() {let { slug } = useParams();return Now showing post {slug};
    }ReactDOM.render(,node
    );
    

    useRouteMatch
    useRouteMatch钩子尝试以与相同的方式匹配当前URL。它主要用于在不实际呈现的情况下访问匹配数据

    import { Route } from "react-router-dom";function BlogPost() {return ( {// Do whatever you want with the match...return ;}}/>);
    }
    

    使用useRouteMatch的话就可以不实际渲染出了

    import { useRouteMatch } from "react-router-dom";function BlogPost() {let match = useRouteMatch("/blog/:slug");// Do whatever you want with the match...return ;
    } 
    

    路由传参
    通配符传参
    Route定义方式:

       
    

    Link组件:

    通配符   
    

    参数获取:

    this.props.match.params.name   
    

    优点:简单快捷,并且,在刷新页面的时候,参数不会丢失。

    缺点:只能传字符串,并且,如果传的值太多的话,url会变得长而丑陋。

    如果,你想传对象的话,可以用JSON.stringify(),想将其转为字符串,然后另外的页面接收后,用JSON.parse()转回去。

    query
    Route定义方式:

       
    

    Link组件:

    var query = {pathname: '/query',querthis.props.location.query
    y: '我是通过query传值 '
    } 
    query
    

    参数获取:

    this.props.location.query
    

    优点:优雅,可传对象 缺点:刷新页面,参数丢失

    state传参
    Route定义方式:

    state
    

    Link组件:

    var state = {pathname: '/state',state: '我是通过state传值'}
    

    参数获取:

    this.props.location.state   
    

    优点:优雅,可传对象 缺点:刷新页面,参数丢失


    本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

    相关文章

    立即
    投稿

    微信公众账号

    微信扫一扫加关注

    返回
    顶部