• react路由(标签属性、Hooks、路由跳转、传值、守卫、懒加载)总结大全


    常用总结


    一、基本的

    1、BrowserRouter
    表示一个路由的跟容器,将来所有跟路由相关的东西,都要包裹在其中
    2、HashRouter  
    表示一个路由的跟容器,将来所有跟路由相关的东西,都要包裹在其中
    3、Route
    具有两种身份:
    1.它是一个路由匹配规则;
    2.它是一个占位符,表示将来匹配到的组件都放到这个位置 ( 类似 vue中 <router-view/> )
    <Route
      exact  // 精确匹配 switch 与 exact 需要配合使用
      path='/my'
      component={My}}
    ></Route>
    4、Link
    表示一个路由的连接;
    在页面渲染的是a标签;
    进行的是路由切换跳转,整个单页面已经切换,而且能知道指向的路径是否是一个有效的路由
    <Link to="/my">我的</Link>
    5、NavLink 
    表示一个路由的连接;
    是<Link>的一个特定版本,会在匹配上当前的url的时候给已经渲染的元素添加参数,组件的属性有
    **activeClassName(string):设置选中样式,默认值为active
    **activeStyle(object):当元素被选中时,为此元素添加样式
    exact(bool):为true时,只有当导致和完全匹配class和style才会应用
    strict(bool):为true时,在确定为位置是否与当前URL匹配时,将考虑位置pathname后的斜线
    isActive(func)判断链接是否激活的额外逻辑的功能
    
    <NavLink to="/my">我的</NavLink>
    <NavLink activeStyle={{color: 'red'}} to='/about'>toAbout</NavLink>
    <NavLink to="/my" activeClassName="selected">My组件</NavLink>
    6、Redirect
    路由重定向
    (1)、当用户访问某界面时,该界面并不存在,此时用Redirect重定向,重新跳到一个我们自定义的组件里。
    (2)、一般都放在 Switch 内,且放到最后一行,即上述路由均未匹配到,则重定向到哪里
    
    举例
    render() {
        return (
          <Router>
            <div>
              <li><NavLink to="/">Home</NavLink></li>
              <li><NavLink to="/about">About</NavLink></li>
              <li><NavLink to="/news">News</NavLink> </li>   <br/>
    
              <Switch>
                <Route path="/" exact component={Home} />
                <Route path="/about" component={About} />
                <Route path="/news" component={News} />
                <Redirect to="/" /> 
              </Switch>
              
            </div>
          </Router>
        );
      }
    7、Switch
    路由匹配,只显示匹配到的第一个路由,一般配合 exact,精确匹配到具体某一个路由
    
    (1)、exact
    是精准匹配,只有路径完全一致才能被匹配到
    
    (2)、举例
    同时加上 Switch 和 exact,击哪个链接就能出来相应的页面;
    如果没有Switch也没有exact,不管点击哪个链接都会有path=’/的页面’,
    如果不加Route 里不加 exact,那么凡是Link里面 to 的路径包含了/( /about, /topic 都包含了 / ,当点击about或者topic的Link的时候,path=’/'的路由都会匹配到,Switch匹配到了一个就停止向下匹配),
    那么就会被匹配到,于是Switch就不继续匹配下去
    如:
    render() {
         return (
             <Router>
                <ul>
                    <li>
                        <Link to="/">main</Link>
                    </li>
                    <li>
                        <Link to="/about">about</Link>
                    </li>
                    <li>
                        <Link to="/topic">topic</Link>
                    </li>
                </ul>
                <Route  path="/" component={Main}></Route>
                <Route  path="/about" component={About}></Route>
                <Route  path="/topic" component={Topic}></Route>
             </Router>
         );
     }
    }


    二、Hooks Routing相关
    // Please note: You need to be using React >= 16.8 in order to use any of these hooks!
    5.1版本的React-Router,带来了useHistory,useLocation,useParams,useRouteMatch四个钩子函数。

    8、useHistory
    使用history
    
    属性(常用)
    go(n)
    goBack(n)
    goForward()
    length
    location ( 路由信息 )
    push
    replace
    
    举例
    import { useHistory } from "react-router-dom";
    
    function BackButton() {
      let history = useHistory();
      return (
        <>
          <button type="button" onClick={() => history.push("/home")}>
            去home页面
          </button>
          <button type="button" onClick={() => history.goBack()}>
            回去
          </button>
        </>
      );
    }
    9、useLocation
    查看当前路由:
    
    const location = useLocation();
    console.log(location);
    输出
    pathname: "/home"
    search: ""
    hash: ""
    state: undefined
    10、useParams
    获取路由中的params。
    
    举例
    import React from "react";
    import ReactDOM from "react-dom";
    import {
      BrowserRouter as Router,
      Route,
      Switch,
      useParams
    } from "react-router-dom";
    
    function BlogId() {
      let { id } = useParams();
      return <div>{id}</div>;
    }
    
    ReactDOM.render(
      <Router>
        <div>
          <Switch>
            <Route path="/blog/:id">
              <BlogId />
            </Route>
          </Switch>
        </div>
      </Router>,
      document.getElementById("root")
    );
    11、useRouteMatch (暂无使用过)
    与<Route>相同的方式匹配当前URL。在无需实际呈现<Route>的情况下访问匹配数据最有用。
    参考网上例子:
    // before
    import { Route } from 'react-router-dom'
    
    function App() {
      return (
        <div>
          {/* ... */}
          <Route
            path="/BLOG/:slug/"
            strict
            sensitive
            render={({ match }) => {
              return match ? <BlogPost match={match} /> : <NotFound />
            }}
          />
        </div>
      )
    }
    
    // after
    import { useRouteMatch } from 'react-router-dom'
    
    function App() {
      let match = useRouteMatch({
        path: '/BLOG/:slug/',
        strict: true,
        sensitive: true
      })
    
      return (
        <div>
          {/* ... */}
          {match ? <BlogPost match={match} /> : <NotFound />}
        </div>
      )
    }

    三、其他

    12、BrowserRouter 与 HashRouter 区别
    React-Router 是建立在 history 之上的,常见的history路由方案有三种形式,分别是:
    
    (1)、hashHistory
    hashHistory 使用 URL 中的 hash(#)部分去创建路由,举例来说,用户访问http://www.aaaaaa.com/,实际会看到的是http://www.aaaaaa.com/#/。
    
    (2)、browserHistory
    browserHistory 是使用 React-Router 的应用推荐的 history方案。它使用浏览器中的 History API 用于处理 URL,创建一个像aaaaaa.com/list/21212323 这样真实的 URL
    当刷新页面时,浏览器会向服务器请求,服务器实际会去找根目录下对应的文件,发现找不到,因为实际上我们的服务器并没有这样的 物理路径/文件 或没有配置处理这个路由,所有内容都是通过React-Router去渲染React组件,自然会报404错误。
    
    (3)、createMemoryHistory (暂时没有用到过)
    Memory history 不会在地址栏被操作或读取。这就解释了我们是如何实现服务器渲染的。同时它也非常适合测试和其他的渲染环境(像 React Native )。和另外两种history的一点不同是你必须创建它,这种方式便于测试。
    
    (4)、两种解决方法
    使用hashHistory,不用做额外处理
    使用browserHistory,服务器需要进行相关路由配置(由后端处理,或nginx配置)
    详见 https://www.thinktxt.com/react/2017/02/26/react-router-browserHistory-refresh-404-solution.html
    13、自定义单击事件处理程序。
    e.preventDefault():阻止默认事件
    e.stopPropagation():阻止事件冒泡
    14、路由嵌套
    详见之前的博客
    https://www.cnblogs.com/-roc/p/14518513.html
    15、react 路由 进阶 之 封装使用(同vue)
    详见之前的博客
    https://www.cnblogs.com/-roc/p/14504557.html

    四、路由

    1、路由跳转

    (1)标签跳转
    import { Link, NavLink } from "react-router-dom";
    Link, NavLink标签,属性为:to,如:
    <Link to="/my">我的</Link>
    <NavLink to="/my">我的</NavLink>
    (2)js跳转(类组件)
    push
    replace
    go
    goBack
    goForward
    如
    this.props.history.push()
    
    事例,如:
    class Dear extends React.Component {
      constructor (props) {
        this.state = {}
      }
      toMy () {
        this.props.history.push('/my')
      }
      render () {
        return(
          <button onClick={this.toMy.bind(this)}/>
        )
      }
    }
    (3)hooks跳转(函数组件)
    import { useHistory } from "react-router-dom";
    const history = useHistory();
    {/* history 中包含与js相同的属性 */}
    function Dear () {
      const toMy = () => {
        history.push('/my')
      }
      return (
        <button onClick={toMy}/>
      )
    }

     

    2、传参与接收
    (参考地址找不到了)

    (1)params传参(刷新页面后参数不消失)
    配置:<Route path='/demoUrl/:id' component={DemoName}></Route> 
    跳转及传递:
        标签方式:<Link to={'/demoUrl/'+'6'}>跳转按钮</Link>
            或:<Link to={{pathname:'/demoUrl/'+'6'}}>跳转按钮</Link>
    
        导航方式:this.props.history.push('/demoUrl/'+'6')  
            或:this.props.history.push({pathname:'/demoUrl/'+'6'})
    **************使用match***************
    获取:this.props.match.params.id 
    (2)params传参(多个参数)
    state={
        id:88,
        name:'Jack',
    }
    配置:<Route path='/demoUrl/:id/:name' component={DemoName}></Route>  
    跳转及传递:
        标签方式:<Link to={{pathname:`/demoUrl/${this.state.id}/${this.state.name}`}}>跳转按钮</Link>
    
        导航方式:this.props.history.push({pathname:`/demoUrl/${this.state.id}/${this.state.name}`})
        **************使用match***************
    获取:this.props.match.params  
    (3)query传参(刷新页面后参数消失)
    配置:<Route path='/demoUrl' component={DemoName}></Route> 
    跳转及传递:
        标签方式:<Link to={{pathname:'/demoUrl',query:{id:22,name:'dahuang'}}}>跳转按钮</Link>
        导航方式:this.props.history.push({pathname:'/demoUrl',query:{id:22,name:'dahuang'}})
        **************使用location***************
    获取: this.props.location.query.name 
    (4)state传参( 刷新页面后参数不消失,state传的参数是加密的,比query传参好用)
    配置:<Route path='/demoUrl' component={DemoName}></Route> 
    跳转及传递:
        标签方式: <Link to={{pathname:'/demoUrl',state:{id:12,name:'dahuang'}}}>跳转按钮</Link> 
        导航方式:this.props.history.push({pathname:'/demoUrl',state:{id:12,name:'dahuang'}})
        **************使用location***************
    获取: this.props.location.state.name 
    (5)其他说明 用Hooks
    
    (5-1)传递参数
    import { useHistory } from 'react-router-dom'
    history.push({pathname:'/' + pathName, state:{id:12, name:pathName}})
    或将state改为query, params, 或aaa (名字随意起)
    只有state传参,刷新不会丢失
    
    (5-2)接收参数
    
    import { useLocation } from 'react-router-dom'
    const location = useLocation();
    如
    location.query
    location.params
    location.state
    location.aaa  ( 其实 query,params,state,都可以随便起名字 )
    只有state传参,刷新不会丢失

    3、路由守卫(或 路由拦截)

    a、解释:所谓路由守卫,就是将跳转到某一个路由时,先进行一些逻辑判断,若通过则进行顺利跳转,若不通过则做其他逻辑处理
    
    b、示例:如跳转页面时,要谈判是否在登录状态,若在则跳转到该页面,若不在则跳回登录页,等
    
    c、vue中的全局守卫
    const router = new VueRouter({ ... })
    router.beforeEach((to, from, next) => {
    })
    vue在所有的路由跳转前,在beforeEach中可以监听所有的路由跳转,如果符合规则,就进行跳转,如果不符合,那么就跳转到我指定的位置。
    
    d、react-router为什么没有呢
    react-router当中,为什么不能提供同样的api呢?作者在github中回复到:
    You can do this from within your render function. JSX doesn't need an API for this because it's more flexible.

    --(1)路由表

    import Home from '需要展示的页面'
    var routes = [
      {path: "/", name: "home", component: Home, auth: true},
      {path: "/my", name: "my", component: My, auth: true},
      {path: "/404", name: "404", component: 404, auth: false}
    ]
    // auth 是否需要登录
    export default routes ;

    --(2)路由高阶组件 封装 

    import React, { Component } from "react";
    import { Route, Redirect } from "react-router-dom";
    class PrivateRoute extends Component {
      render() {
        // routerConfig 为具体某项路由表信息,详见 --(3) 具体使用
        const { routerConfig, location } = this.props;
        const { pathname } = location;
        const isLogin = sessionStorage.getItem("token");
        // 如果该路由不用进行权限校验,登录状态下登陆页除外
        // 因为登陆后,无法跳转到登陆页
    
        -------------// 这部分代码,是为了在非登陆状态下,访问不需要权限校验的路由  Start--------------
        const targetRouterConfig = routerConfig.find(
          // find()方法,用于找出第一个符合条件的数组成员。
          (item) => {
            // 全局去掉空格
            return item.path.replace(/s*/g,"") === pathname
          } 
        );
        if (targetRouterConfig && !targetRouterConfig.auth && !isLogin) {
          const { component } = targetRouterConfig;
          return <Route exact path={pathname} component={component} />
        }
        -----------------// 这部分代码,是为了在非登陆状态下,访问不需要权限校验的路由  End--------------
    
        -----------------// 这部分代码,是为了在需要登陆状态下 进行验证--------------
        if (isLogin) {
          // 如果是登陆状态,想要跳转到登陆,重定向到主页
          if (pathname === "/login") {
            return <Redirect to="/" />;
          } else {
            // 如果路由合法,就跳转到相应的路由
            if (targetRouterConfig) {
              return (<Route path={pathname} component={targetRouterConfig.component} />);
            } else {
              // 如果路由不合法,重定向到 404 页面
              return <Redirect to="/404" />;
            }
          }
        } else {
          // 非登陆状态下,当路由合法时且需要权限校验时,跳转到登陆页面,要求登陆
          if (targetRouterConfig && targetRouterConfig.auth) {
            console.log('跳转登录登录')
            return <Redirect to="/login" />;
          } else {
            // 非登陆状态下,路由不合法时,重定向至 404
            return <Redirect to="/404" />;
          }
        }
      }
    }
    export default PrivateRoute

    --(3)使用 路由高阶组件

    import React from 'react';
    import {Switch, BrowserRouter} from 'react-router-dom'
    // 你的高阶组件
    import PrivateRoute from './PrivateRoute'
    // 你的路由表 ,或使用 自动化配置的路由表 https://www.cnblogs.com/-roc/p/14544531.html
    import routes from '../views/index'
    
    function router() {
      return (
        <BrowserRouter>
          <Switch>
            // 凭经验编写,有问题欢迎评论修改
            routes.forEach(item => {
              return (
                <PrivateRoute key={item.path} routerConfig={item} />
              )
            })
          </Switch>
        </BrowserRouter>
      );
    }
    
    export default router;
    
    参考
    https://www.jianshu.com/p/16f35c090706?utm_campaign=haruki
    https://www.jianshu.com/p/f8926ed59d25
    https://zhuanlan.zhihu.com/p/162942121

    4、路由懒加载

    --(1)安装
    yarn add react-loadable
    
    --(2)创建通用工具类:
      如: src/util/loadable.js
    
    import React from 'react';
    import Loadable from 'react-loadable';
     
    //通用的过场组件
    const LoadingComponent =()=>{
        return (
            <div>loading</div>
        )
    }
     
    //过场组件默认采用通用的,若传入了loading,则采用传入的过场组件
    export default (loader,loading = LoadingComponent)=>{
        return Loadable({
            loader,
            loading
        });
    }
    --(3)router里面调用方式改为如下
    /*配置路由*/
    import React, { Fragment } from 'react'
    import { BrowserRouter, Route } from 'react-router-dom'
    import loadable from '../util/loadable'
     
    const Home = loadable(()=>import('@pages/home'))
     
    const Routes = () => (
        <BrowserRouter>
            <Route path="/home" component={Home}/>
        </BrowserRouter>
    );
     
    export default Routes
    
    --(4)
    封装之后,laodable只需写一次,改变的只是组件的引入方式,这样一来就方便多了,
    
    react-loadable是以组件级别来分割代码的,这意味着,我们不仅可以根据路由按需加载,还可以根据组件按需加载,使用方式和路由分割一样,只用修改组件的引入方式即可
    
    参考
    https://www.cnblogs.com/crazycode2/p/12210778.html

    写在最后

    https://reactrouter.com/web/api/Hooks/useroutematch

    此为官网,感觉写的不详细,自己又进行了总结这篇

  • 相关阅读:
    sql STUFF用法
    关于原型链
    原生js事件绑定
    http常见7种请求
    关于linux的一些常用的指令
    flex布局详解
    html5 新增元素以及css3新特性
    css浮动以及清除
    css 浮动
    计算机网络
  • 原文地址:https://www.cnblogs.com/-roc/p/14522546.html
Copyright © 2020-2023  润新知