React-router6

router6.0

Install:

	安装: npm i react-router-dom

use

Level 1 routing

import React from 'react';
import {
    
    Route, Routes} from "react-router-dom";
import Film from "../views/film";
import Cinema from "../views/Cinema";
import Center from "../views/Center";

function MRouter(props) {
    
    
    return (
         <Routes>
             {
    
    /*Route一定要包裹在Routes组件内部*/}
            <Route path="/film" element={
    
    <Film />}></Route>
            <Route path="/cinema" element={
    
    <Cinema />}></Route>
            <Route path="/center" element={
    
    <Center />}></Route>
            
              <Route path="/" element={
    
    <Redirect to="/film"></Redirect>}></Route>
             <Route path="*" element={
    
    <NotFound></NotFound>}></Route>
        </Routes>
    );
}

export default MRouter;

Then hang MRrouter to App.js

app.js

import logo from './logo.svg';
import {
    
    HashRouter} from 'react-router-dom'
//HashRouter: 哈希模式
//BrowserRouter:浏览器模式
import './App.css';
import MRouter from "./router";
function App() {
    
    
  return (
      <HashRouter>
          <MRouter></MRouter>
      </HashRouter>
  );
}

export default App;

route redirection

index means: does not match other sub-routes, only displays the component when the parent component is routed, and is used for nested routes.

​ To solve the problem that the current nested route has multiple sub-routes but cannot confirm which sub-route to render by default, you can add the index attribute to make the default route. The difference between the index route and other routes is that it does not have a path attribute and shares the same route with the parent route. a path

The first solution: Navigate

import {
    
    Navigate, NavLink, Route, Routes} from "react-router-dom";
{
    
    /*     路由重定向*/}
{
    
    /*     *表示万能匹配,当以上路由都未匹配到时,才会走下面的匹配,渲染film组件*/}
      <Route path="*" element={
    
    <Navigate to="/film"></Navigate>}></Route>

The second solution: custom redirect (useNavigate hook function)


```js
  <Route path="*" element={<Redirect to="/film"></Redirect>}></Route>
  
  // Redirect组件:
import React, {useEffect} from 'react';
import {useNavigate} from "react-router-dom";

function Redirect({to}) {
    const navigate = useNavigate() //useNavigate: react-router-dom提供的钩子函数,返回一个对象
    useEffect(() => {
        navigate(to,{replace: true}) //replace表示关闭之前的页面
    },[])
    return null
}

export default Redirect;

nested routes

Partial writing of nested routing router.js:

 <Route path="/film"  element={
    
    <Film />}>
                {
    
    /*index表示默认展示的子路由 与父路由展示同一路径*/}
                <Route index element={
    
    <Redirect to="/film/nowPlaying"></Redirect>} ></Route>
                <Route path="/film/comingSoon" element={
    
    <ComingSoon />}></Route>
                {
    
    /*相对路径写法: 相对于父路由的写法*/}
                <Route path="nowPlaying" element={
    
    <NowPlaying />}></Route>
                <Route path="comingSoon" element={
    
    <ComingSoon />}></Route>
            </Route>
            <Route path="/cinema" element={
    
    <Cinema />}></Route>
            <Route path="/center" element={
    
    <Center />}></Route>
</Route>

Placeholders should be left in the Film component:

import React from 'react';
import {
    
    Outlet} from "react-router-dom";

function Film(props) {
    
    
    return (
        <div>
            {
    
    /*注意路径关系*/}
            <div style={
    
    {
    
    height:'200px',background:'lightblue'}}>大轮播</div>
            {
    
    /*路由容器: 类似于view的router-view*/}
            <Outlet></Outlet>
        </div>
    );
}

export default Film;

Declarative and programmatic navigation

​ Declarative navigation:

​ Programmatic navigation: location.href="#"

Declarative Navigation

import React from 'react';
import './tabbar.css'
import {
    
    Link,NavLink} from "react-router-dom";
function TabBar(props) {
    
    
    return (
        <div>

            <ul className="footer">
                <li>
                    {
    
    /*<Link to="/film"> 电影</Link>*/}
                    {
    
    /*NavLink具有Link的一切功能,并且具有高亮显示的功能*/}
                    {
    
    /*className是给NavLink的一个属性,支持传入回调函数*/}
                    <NavLink to="/film" className={
    
    ({
     
     isActive}) =>
                        isActive ? 'tabbar_active' : ''
                    }> 电影</NavLink>
                </li>
                <li>
                    <Link to="/cinema"> 影院</Link>
                </li>
                <li>
                    <Link to="/center"> 个人中心</Link>
                </li>
            </ul>
        </div>
    );
}

export default TabBar;

programmatic navigation

import React from 'react';
import {
    
    useNavigate} from "react-router-dom";

function NowPlaying(props) {
    
    
    const navigate = useNavigate()
    const handlePage = (params) => {
    
    
        navigate(`/detail?id=${
      
      params}`)

        //    search传参(URLsearch) /detail?id=100
        //    路由传参 /detail/1000
    }
    return (
        <div>
            {
    
    
                Array(20).fill(0).map((item,index) => index).map(item =>
                    <div key={
    
    item} onClick={
    
    () => {
    
    
                       handlePage(item)
                    }}>{
    
    item}</div>
                )
            }
        </div>
    );
}
export default NowPlaying;

​ Detail.js

import React from 'react';
import {
    
    useSearchParams} from "react-router-dom";

function Detail(props) {
    
    
    const [searchParams, setSearchParams] = useSearchParams()
    console.log({
    
    searchParams})
    console.log(searchParams.get('id')) // 获取传过来的参数
    return (
        <div>Detail
        <button onClick={
    
    () => {
    
    
            setSearchParams({
    
    id: 8})
        }}>猜你喜欢</button>
        </div>
    );
}

export default Detail;

dynamic routing

//路由配置
  <Route path="/detail/:id" element={
    
    <Detail />}></Route>
// films.js
import React from 'react';
import {
    
    useNavigate} from "react-router-dom";

function NowPlaying(props) {
    
    
    const navigate = useNavigate()
    const handlePage = (params) => {
    
    
        navigate(`/detail/${
      
      params}`)
    }
    return (
        <div>
            {
    
    
                Array(20).fill(0).map((item,index) => index).map(item =>
                    <div key={
    
    item} onClick={
    
    () => {
    
    
                       handlePage(item)
                    }}>{
    
    item}</div>
                )
            }
        </div>
    );
}

export default NowPlaying;

//detail.js
import React from 'react';
import {
    
    useSearchParams, useParams} from "react-router-dom";

function Detail(props) {
    
    
    //接受动态路由参数
    const obj = useParams() 
    console.log(obj)// {id: 7}

    return (
        <div>Detail -{
    
    obj.id}
       <button onClick={
    
    () => {
    
    
            // setSearchParams({id: 8})
            navigate('/detail/1000')
        }}>猜你喜欢</button>
    );
}

export default Detail;

route interception

 {
    
    /* element只会走一遍,只会走组件的生命周期,三木运算符只会走一遍,解决办法就是再封装一个组件*/}
            <Route path="/center" element={
    
    <AuthComponent>
                {
    
    /*需要鉴权的组件都可以放在AuthComponent*/}
                <Center></Center>
            </AuthComponent>}></Route>

//鉴权组件 
function AuthComponent({
     
     children}){
    
    
    return localStorage.getItem('token') ? children : <Redirect to="/login"></Redirect>
}

routing pattern

hashRouter

BrowserRouter: requires backend configuration support

import logo from './logo.svg';
import {
    
    BrowserRouter, HashRouter} from 'react-router-dom'
//HashRouter: 哈希模式
//BrowserRouter:浏览器模式
import TabBar from "./conponents/TabBar/Tabbar";
import './App.css';
import MRouter from "./router";
function App() {
    
    
  return (
      <BrowserRouter>
          {
    
    /*<HashRouter>*/}
              <MRouter></MRouter>

              <TabBar></TabBar>
          {
    
    /*</HashRouter>*/}
      </BrowserRouter>
  );
}

export default App;

Class component jump method

There is no withRouter in v6, which can be self-encapsulated

//filmItem
import React, {
    
    Component} from 'react';
import WithRouter from "../../conponents/WithRouter";
class FilmIteMcLass extends Component {
    
    

    render() {
    
    
        console.log(this.props.history)
        return (
            <div>
                <li onClick={
    
    () => {
    
    
                    this.handleClick(this.props.item)
                }}>{
    
    this.props.item}</li>
            </div>
        );
    }
    handleClick(id){
    
    
        console.log({
    
    id})
        this.props.history.push(`/detail/${
      
      id}`)
    }
}


export default WithRouter(FilmIteMcLass);

// 自我封装withRouter
import React from'react';
import {
    
    useNavigate,useParams,useLocation } from'react-router-dom';
function WithRouter(Component) {
    
    
    return function WithRouter(props) {
    
     //react-hooks需要放在组件中,因此不建议放在匿名函数和箭头函数中,否则会报错
        const push = useNavigate() //跳转
        const match = useParams() // 获取传参
        const location = useLocation() // 获取路径

        return <Component {
    
    ...props} history={
    
    {
    
    push,match,location}}></Component>
    }
}
export default WithRouter;

Performance optimization - lazy loading of routes

// 懒加载封装
function LazyLoad(path){
    
    
    const Comp = React.lazy(() => import(`../views/${
      
      path}`))
    return(
        <React.Suspense fallback={
    
    <>加载中</>}>
            <Comp></Comp>
        </React.Suspense>

    )
}
//使用
// 要删除import的路径
<Route path="nowPlaying" element={
    
    LazyLoad("filmModules/NowPlaying")}></Route>
<Route path="/cinema" element={
    
    LazyLoad("Cinema")}></Route>

Lazy-loaded modules will be abstracted into a single js file, so there are more files than those in the project that do not apply lazy-loading.

useRoutes hook to configure routing

import  React from 'react';
import {
    
    Navigate, NavLink, Route, Routes, useRoutes} from "react-router-dom";
import Redirect from "../conponents/Redirect";

function MRouter(props) {
    
    
    const element = useRoutes([
        {
    
    
            path: '/film',
            element: LazyLoad("film"),
            children:[
                {
    
    
                    path:'',
                    element: <Redirect to="/film/nowPlaying"></Redirect>
                },
                {
    
    
                    path: 'nowPlaying',
                    element: LazyLoad("filmModules/NowPlaying")
                },
                {
    
    
                    path:'comingSoon',
                    element: LazyLoad('filmModules/ComingSoon')
                }
            ]
        },
        {
    
    
            path:'/cinema',
            element: LazyLoad('Cinema')
        },
        {
    
    
            path:'/login',
            element:LazyLoad('Login')
        },
        {
    
    
            path:'/center',
            element:<AuthComponent> {
    
    LazyLoad('Center')}</AuthComponent>
        }
    ])
    return (
        element
    );
}

function AuthComponent({
     
     children}){
    
    
    return localStorage.getItem('token') ? children : <Redirect to="/login"></Redirect>
}

function LazyLoad(path){
    
    
    const Comp = React.lazy(() => import(`../views/${
      
      path}`))
    return(
        <React.Suspense fallback={
    
    <>加载中</>}>
            <Comp></Comp>
        </React.Suspense>

    )
}
export default MRouter;

Compared with the method written without hook function:

import React from 'react';
import {
    
    Navigate, NavLink, Route, Routes} from "react-router-dom";
import Film from "../views/film";
// import Cinema from "../views/Cinema";
import Center from "../views/Center";
import Redirect from "../conponents/Redirect";
import NotFound from "../views/NotFound";
// import NowPlaying from "../views/filmModules/NowPlaying";
import ComingSoon from "../views/filmModules/ComingSoon";
import Detail from "../views/Detail";
import Login from "../views/Login";

function MRouter(props) {
    
    
    return (
         <Routes>
             {
    
    /*Route一定要包裹在Routes组件内部*/}
            {
    
    /* index表示: 不匹配其他子路由,只在父组件路由的时候显示该组件,用于嵌套路由*/}
            <Route path="/film"  element={
    
    <Film />}>
                {
    
    /*index表示默认展示的子路由 与父路由展示同一路径*/}
                <Route index element={
    
    <Redirect to="/film/nowPlaying"></Redirect>} ></Route>
                <Route path="/film/comingSoon" element={
    
    <ComingSoon />}></Route>
                {
    
    /*相对路径写法: 相对于父路由的写法*/}
                <Route path="nowPlaying" element={
    
    LazyLoad("filmModules/NowPlaying")}></Route>
                <Route path="comingSoon" element={
    
    <ComingSoon />}></Route>
            </Route>
            <Route path="/cinema" element={
    
    LazyLoad("Cinema")}></Route>
            {
    
    /* element只会走一遍,只会走组件的生命周期,三木运算符只会走一遍,解决办法就是再封装一个组件*/}
            <Route path="/center" element={
    
    <AuthComponent>
                {
    
    /*需要鉴权的组件都可以放在AuthComponent*/}
                <Center></Center>
            </AuthComponent>}></Route>
            <Route path="/detail/:id" element={
    
    <Detail />}></Route>
             <Route path="/login" element={
    
    <Login></Login>}></Route>
        {
    
    /*     路由重定向*/}
        {
    
    /*     *表示万能匹配,当以上路由都未匹配到时,才会走下面的匹配,渲染film组件*/}
        {
    
    /*     <Route path="*" element={<Navigate to="/film"></Navigate>}></Route>*/}
             <Route path="/" element={
    
    <Redirect to="/film"></Redirect>}></Route>
             <Route path="*" element={
    
    <NotFound></NotFound>}></Route>

        </Routes>
    );
}
function AuthComponent({
     
     children}){
    
    
    return localStorage.getItem('token') ? children : <Redirect to="/login"></Redirect>
}

function LazyLoad(path){
    
    
    const Comp = React.lazy(() => import(`../views/${
      
      path}`))
    return(
        <React.Suspense fallback={
    
    <>加载中</>}>
            <Comp></Comp>
        </React.Suspense>

    )
}
export default MRouter;

The writing method of react-ruter6 is very similar to that of vue, especially the encapsulation of the useRouteList hook, which is basically the same as that of vue

Guess you like

Origin blog.csdn.net/weixin_44813858/article/details/132326727