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

此為官網,感覺寫的不詳細,自己又進行了總結這篇


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM