react-router基础知识1

99 阅读4分钟

路由

什么是路由

路由维护了URL地址和组件的映射关系,通过这个映射关系,可以根据不同的URL地址,去渲染不同的组件

react-router

安装

npm install react-router-dom

使用

监听模式

无论是Link还是Route都只能放到BrowserRouter和HashRouter中才有效

  • 在企业开发中如果不需要兼容低级版本浏览器, 建议使用BrowserRouter
  • 如果需要兼容低级版本浏览器, 那么只能使用HashRouter

Link

用于修改URL的资源地址

  • to
    • 跳转URL

NavLink

功能与Link类似。不同点:可以设置相关样式,例如激活时的高亮

Routes

Routes-github

  • 类似之前版本的Switch

Route

用于维护URL和组件的关系。Route是一个占用组件,将来它会根据匹配到的资源地址渲染对应的组件

outlet

  • 类似vue的router-view

Navigate

  • 代替了之前的Redirect
import React from "react"
import { BrowserRouter, Routes, Link, Route } from "react-router-dom"
import Home from "./component/view/Home"
import About from "./component/view/About"
import NotFound from './component/view/NotFound'
import Layout from './component/view/Layout'
import User from './component/view/User'
import Login from './component/view/Login'
import './App.css'
import { NavLink } from "react-router-dom"
class App extends React.PureComponent {
    render() {
        return (
            <div id={'app'}>
                <BrowserRouter>
                    {/* <Link to={'/home'} relative='home'>Home</Link>
                    <Link to={'/home/about'} relative='/home/about'>About</Link> */}
                    <nav id="sidebar">
                        <NavLink end to={'/home'}>Home</NavLink>
                        <NavLink end to={'/about'}>About</NavLink>
                        <NavLink end to={'/user'}>User</NavLink>
                    </nav>
                    {/* <Link to={'/home'}>Home</Link>
                    <Link to={'/home/about'}>About</Link> */}
                    <Routes>
                        <Route path="/" element={<Layout />}>
                            <Route index path='/home' element={<Home />} />
                            <Route end path="/about" element={<About />} />
                        </Route>
                        <Route path='user' element={<User />} />
                        <Route path="login" element={<Login />} />
                        {/* <Route path={'/home'} element={<Home />} />
                        <Route path={"/home/about"} element={<About />} /> */}
                        <Route path='*' element={<NotFound />} />
                    </Routes>
                </BrowserRouter>
                {/* <Home></Home>
                <About></About> */}
            </div>
        )
    }
}
export default App
import React from "react"
import { Outlet } from "react-router-dom"
class Layout extends React.PureComponent {
    render() {
        return (
            <div id={'app'}>
                layout
                <Outlet />
            </div>
        )
    }
}
export default Layout
import React from 'react'
import { Navigate } from 'react-router-dom'
class User extends React.PureComponent {
    constructor (props) {
        super(props)
        this.state = {
            isLogin: false
        }
    }
    render() {
        let user = (
            <div>
                <h1>用户界面</h1>
                <p>用户名: jonathan_lee</p>
                <p>密码: www.it666.com</p>
            </div>
        )
        let login = <Navigate to={'/login'} />
        return this.state.isLogin ? user : login
    }
}
export default User

嵌套路由

1.嵌套路由(子路由): 路由里面又有路由, 我们就称之为嵌套路由

import React from "react"
import { BrowserRouter, Routes, Link, Route } from "react-router-dom"
import Home from "./component/view/Home"
import About from "./component/view/About"
import NotFound from './component/view/NotFound'
import Layout from './component/view/Layout'
import User from './component/view/User'
import Login from './component/view/Login'
import './App.css'
import { NavLink } from "react-router-dom"
class App extends React.PureComponent {
    render() {
        return (
            <div id={'app'}>
                <BrowserRouter>
                    {/* <Link to={'/home'} relative='home'>Home</Link>
                    <Link to={'/home/about'} relative='/home/about'>About</Link> */}
                    <nav id="sidebar">
                        <NavLink to={'/home'}>Home</NavLink>
                        <NavLink end to={'/about'}>About</NavLink>
                        <NavLink end to={'/user'}>User</NavLink>
                    </nav>
                    {/* <Link to={'/home'}>Home</Link>
                    <Link to={'/home/about'}>About</Link> */}
                    <Routes>
                        <Route path="/" element={<Layout />}>
                            <Route index path='/home/*' element={<Home />} />
                            <Route end path="/about" element={<About />} />
                        </Route>
                        {/* <Route path='/home/*' element={<Home />} />
                        <Route end path="/about" element={<About />} /> */}
                        <Route path='user' element={<User />} />
                        <Route path="login" element={<Login />} />
                        {/* <Route path={'/home'} element={<Home />} />
                        <Route path={"/home/about"} element={<About />} /> */}
                        <Route path='*' element={<NotFound />} />
                    </Routes>
                </BrowserRouter>
                {/* <Home></Home>
                <About></About> */}
            </div>
        )
    }
}
export default App
import React from "react"
import { NavLink, Routes, Route } from "react-router-dom"
import NotFound from './NotFound'
function Hot() {
    return (
        <div>推荐</div>
    )
}
function TopList() {
    return (
        <div>排行榜</div>
    )
}
function PlayList() {
    return (
        <div>歌单</div>
    )
}
class Home extends React.PureComponent {
    render() {
        return (
            <div id={'app'}>
                Home
                <nav id="sidebar">
                    <NavLink end to={'/home'}>recommand</NavLink>
                    <NavLink end to={'/home/toplist'}>toplist</NavLink>
                    <NavLink end to={'/home/playlist'}>playlist</NavLink>
                </nav>
                <Routes>
                    <Route path='/' element={<Hot />} />
                    <Route path="/toplist" element={<TopList />} />
                    <Route path='/playlist' element={<PlayList />} />
                    <Route path='/*' element={<NotFound />} />
                </Routes>
            </div>
        )
    }
}
export default Home

网友笔记

手动路由跳转

import React from "react"
import { NavLink, Routes, Route } from "react-router-dom"
import widthUseNavigate from "./widthUseNavigate"
import NotFound from './NotFound'
function Hot() {
    return (
        <div>推荐</div>
    )
}
function TopList() {
    return (
        <div>排行榜</div>
    )
}
function PlayList() {
    return (
        <div>歌单</div>
    )
}
class HomeDOM extends React.PureComponent {
    render() {
        return (
            <div id={'app'}>
                Home
                <nav id="sidebar">
                    <NavLink end to={'/home'}>recommand</NavLink>
                    <NavLink end to={'/home/toplist'}>toplist</NavLink>
                    <NavLink end to={'/home/playlist'}>playlist</NavLink>
                    <button onClick={() => { this.btnClick() }}>歌单</button>
                </nav>
                <Routes>
                    <Route path='/' element={<Hot />} />
                    <Route path="/toplist" element={<TopList />} />
                    <Route path='/playlist' element={<PlayList />} />
                    <Route path='/*' element={<NotFound />} />
                </Routes>
            </div>
        )
    }
    btnClick() {
        console.log('this.props', this.props)
        this.props.to('/home/playlist')
        // this.props.history.push('/home/playlist')
    }
}
const Home = widthUseNavigate(HomeDOM)
export default Home

import { useNavigate } from 'react-router-dom'
// 高阶组件包装useNavigate()功能
// 原因:类组件中无法使用useNavigate(),会报错
// React Hook "useNavigate" cannot be called in a class component.
function widthUseNavigate(WrapCompontent) {
    // 设置别名
    WrapCompontent.displayName = `widthUseNavigate${getDisplayName(WrapCompontent)}`
    // console.log('WrapCompontent.displayName', WrapCompontent.displayName)
    return function NavigateCompont() {
        const navigate = useNavigate()
        // 给传入的组件新增一个to方法,传给原始组件的props,在原始组件中通过this.props.to(参数)使用
        return <WrapCompontent to={navigate}></WrapCompontent>
    }
}

// 别名
function getDisplayName(WrapCompontent) {
    // console.log('WrapCompontent', WrapCompontent.displayname, WrapCompontent.name)
    return WrapCompontent.displayname || WrapCompontent.name || 'Component'
}

export default widthUseNavigate

image.png HOC-约定:包装显示名称以便轻松调试

网友笔记

路由传参

<NavLink to={'/home?name=study&age=18'}>Home</NavLink>
<NavLink to={'/home'} state={obj}>Home</NavLink>
import React from "react"
import { NavLink, Routes, Route } from "react-router-dom"
import { useLocation, useParams, useMatches } from "react-router-dom"
import widthUseNavigate from "./widthUseNavigate"
import NotFound from './NotFound'
import qs from 'querystring'
function Hot() {
    return (
        <div>推荐</div>
    )
}
function TopList(props) {
    let params = useParams() // 获取动态参数
    console.log('params', params) // id
    return (
        <div>排行榜</div>
    )
}
function PlayList() {
    return (
        <div>歌单</div>
    )
}
function propsRouteWithRouter(PropsRoute) {
    return (props) => {
        // let match = useMatches()
        // console.log('match', match)
        let params = useParams()
        const search = qs.parse(useLocation().search.slice(1)) // 获取get传参形式的数据
        const state = useLocation().state  // Link | NavLink 通过state传的参数
        console.log('params', params, search, state)
        params = Object.assign(params, search, state)
        return <PropsRoute {...props} params={params} />
    }
}
class HomeDOM extends React.PureComponent {
    constructor (props) {
        super(props)
        this.state = {
            ...this.props.params
        }
    }
    render() {
        console.log('this.props', this.props.params, this.state)
        return (
            <div id={'app'}>
                <div>data: {this.props.params.name}</div>
                Home
                <nav id="sidebar">
                    <NavLink end to={'/home'}>recommand</NavLink>
                    <NavLink end to={'/home/toplist/123123'}>toplist</NavLink>
                    <NavLink end to={'/home/playlist'}>playlist</NavLink>
                    <button onClick={() => { this.btnClick() }}>歌单</button>
                </nav>
                <Routes>
                    <Route path='/' element={<Hot />} />
                    <Route path="/toplist/:id" element={<TopList />} />
                    <Route path='/playlist' element={<PlayList />} />
                    <Route path='/*' element={<NotFound />} />
                </Routes>
            </div>
        )
    }
    btnClick() {
        console.log('this.props', this.props)
        this.props.to('/home/playlist')
        // this.props.history.push('/home/playlist')
    }
}
const Home = widthUseNavigate(propsRouteWithRouter(HomeDOM))
export default Home

路由统一管理

现在虽然我们能通过路由实现组件切换, 但是现在我们的路由都比较分散, 不利于我们管理和维护 所以React也考虑到了这个问题, 也给我们提供了统一管理路由的方案

useRoutes

import React from "react"
import { BrowserRouter, useRoutes, Routes, Link, Route, Outlet } from "react-router-dom"
import Home from "./component/view/Home"
import About from "./component/view/About"
import NotFound from './component/view/NotFound'
import Layout from './component/view/Layout'
import User from './component/view/User'
import Login from './component/view/Login'
import './App.css'
import { NavLink } from "react-router-dom"
import DefineRoutes from './router/index'
class App extends React.PureComponent {
    render() {
        let obj = {
            name: 'sss',
            age: 16,
            gender: 'man'
        }
        return (
            <div id={'app'}>
                <BrowserRouter>
                    {/* <Link to={'/home'} relative='home'>Home</Link>
                    <Link to={'/home/about'} relative='/home/abo ut'>About</Link> */}
                    <nav id="sidebar">
                        {/* <NavLink to={'/home?name=study&age=18'}>Home</NavLink> */}
                        <NavLink to={'/home'} state={obj}>Home</NavLink>
                        <NavLink end to={'/about'}>About</NavLink>
                        <NavLink end to={'/user'}>User</NavLink>
                    </nav>
                    {/* <Link to={'/home'}>Home</Link>
                    <Link to={'/home/about'}>About</Link> */}
                    {/* <Routes>
                        <Route path="/" element={<Layout />}>
                            <Route index path='/home/*' Component={Home} />
                            <Route end path="/about" element={<About />} />
                        </Route>
                        <Route path='user' element={<User />} />
                        <Route path="login" element={<Login />} />
                        <Route path='*' element={<NotFound />} />
                    </Routes> */}
                    <DefineRoutes></DefineRoutes>
                </BrowserRouter>
                {/* <Home></Home>
                <About></About> */}
            </div>
        )
    }
}
export default App
import React from "react"
import { NavLink, Routes, Route } from "react-router-dom"
import { useLocation, useParams, useMatches, Outlet } from "react-router-dom"
import widthUseNavigate from "./widthUseNavigate"
import NotFound from './NotFound'
// import DefineRoutes from '../../router/index'
import qs from 'querystring'
export function Hot() {
    return (
        <div>推荐</div>
    )
}
export function TopList(props) {
    let params = useParams()
    console.log('params', params) // id
    return (
        <div>排行榜</div>
    )
}
export function PlayList() {
    return (
        <div>歌单</div>
    )
}
function propsRouteWithRouter(PropsRoute) {
    return (props) => {
        // let match = useMatches()
        // console.log('match', match)
        let params = useParams()
        const search = qs.parse(useLocation().search.slice(1))
        const state = useLocation().state
        console.log('params', params, search, state)
        params = Object.assign(params, search, state)
        return <PropsRoute {...props} params={params} />
    }
}
class HomeDOM extends React.PureComponent {
    constructor (props) {
        super(props)
        this.state = {
            ...this.props.params
        }
    }
    render() {
        console.log('this.props', this.props.params, this.state)
        return (
            <div id={'app'}>
                <div>data: {this.props.params.name} {this.state.age}</div>
                Home
                <nav id="sidebar">
                    <NavLink end to={'/home'}>recommand</NavLink>
                    <NavLink end to={'/home/toplist/123123'}>toplist</NavLink>
                    <NavLink end to={'/home/playlist'}>playlist</NavLink>
                    <button onClick={() => { this.btnClick() }}>歌单</button>
                </nav>
                {/* <Routes>
                    <Route path='/' element={<Hot />} />
                    <Route path="/toplist/:id" element={<TopList />} />
                    <Route path='/playlist' element={<PlayList />} />
                    <Route path='/*' element={<NotFound />} />
                </Routes> */}
                <Outlet />
            </div>
        )
    }
    btnClick() {
        console.log('this.props', this.props)
        this.props.to('/home/playlist')
        // this.props.history.push('/home/playlist')
    }
}
const Home = widthUseNavigate(propsRouteWithRouter(HomeDOM))
export default Home
import { memo } from 'react'
import Home from "../component/view/Home"
import About from "../component/view/About"
import NotFound from '../component/view/NotFound'
import Layout from '../component/view/Layout'
import User from '../component/view/User'
import Login from '../component/view/Login'
import { Hot, TopList, PlayList } from '../component/view/Home'
import { useRoutes } from "react-router-dom"
const DefineRoutes = memo(() => {
    const routers = useRoutes(
        [
            {
                path: '/',
                element: <Layout />,
                children: [
                    {
                        path: 'home',
                        element: <Home />,
                        children: [
                            {
                                path: '/home',
                                element: <Hot />,
                            },
                            {
                                path: 'toplist/:id',
                                element: <TopList />,
                            },
                            {
                                path: 'playlist',
                                element: <PlayList />,
                            }
                        ]
                    },
                    {
                        path: 'about',
                        element: <About />
                    },
                ]
            },

            {
                path: '/user',
                element: <User />
            },
            {
                path: '/login',
                element: <Login />
            },
            {
                path: '*',
                element: <NotFound />
            },
        ]
    )
    return routers
})

export default DefineRoutes

部分知识点学习