0


react——路由

    前端路由就是把不同路由对应不同的内容或页面对应展示出来。路由可以帮助我们很好的管理页面和代码,增强用户的体验感。路由模式有hash和 history 两种模式,通常用hash模式。在react中,react-router是跨平台的,内置通用组件和通用Hooks。react-router-dom是在react-router基础上提供了Link和NavLink,而且依赖history库提供了两个浏览器端适用的BrowserRouter和HashRouter,现在的项目基本都是使用react-router-dom。本篇文章介绍了使用频率高和我接触到的路由内容。

一、路由原理

    通俗的来说,路由用来管理url地址和视图之间的关系,一个地址对应一个页面要展示的内容,下面展示的地址就是hash模式(/#/)

原理:

​ 1、准备视图(html)

​ 2、准备路由的路线(可以是一个对象,键名是路线名称和值是视图地址)

​ 3、通过hash地址的路线,获取“视图地址”

​ 4、在指定标签中,加载需要的视图页面

原理图灵魂画手

二、使用

(一)安装

npm i react-router-dom@5

(二)导入

import { ...通用组件 } from 'react-router-dom'

(三)使用

<BrowserRouter >
   <Route path="路径" component={组件}></Route>

</BrowserRouter >

三、通用组件

(一)BrowserRouter

    history模式,页面跳转原理是使用了pushState、replaceState。使用这个包裹,路由的形式将以/展示,可以通过as重命名,一般见到的形式为:BrowserRouter as Router(把BrowserRouter 重命名为Router )

    **属性:**

            basename(string):所有位置的基本url,应用是从服务器上的子目录提供的,则需要将其设置为子目录,格式正确的基本名称应以斜杆开头,但不能以斜杆结尾

            getUserConfirmation(fn):用于确认导航的功能,默认使用window.confirm
<BrowserRouter>
        <Route path='/films' component={Films}></Route>

        <Route path='/home' component={Home}></Route>
</BrowserRouter>

(二)HashRouter

     hash模式,页面跳转原理是使用了location.hash、location.replace。使用这个包裹,路由的形式将以/#/展示,虽然长的丑,但是用的比较多
<HashRouter>
        <Route path='/films' component={Films}></Route>

        <Route path='/home' component={Home}></Route>
</HashRouter>

注意:BrowserRouter和HashRouter的区别

1、底层原理不一样

    HashRouter使用的是Url的哈希值

    BrowserRouter使用的是h5的history api,不兼容ie9及以下版本

2、path表现形式不一样HashRouter带个#号

3、HashRouter刷新后对路由state参数的影响,而BrowserRouter是将state保存再history对象中

4、HashRouter可以用于解决一些路径错误相关的问题

(三)Route

    匹配组件,并展示组件。即匹配成功后,组件立即被替换成匹配的组件

属性类型作用pathstr | obj路由匹配路径,没有path属性的Route总是会匹配exactbool为true时,要求全路径匹配(/home)。路由默认为“包含”的(/和/home)都匹配,这意味着多个Route可以同时进行匹配和渲染componentfn | component在地址匹配的时候React的组件才会被渲染,route props也会随着一起被渲染renderfunc内联渲染和包装组件,要求要返回目标组件的使用

<Route path='/films' component={Films} />

或者

<Route path="/" exact render={() => {
return <IndexPage user={user} />
}} />

注意:模糊匹配和精准匹配

    因为exact的存在,分为模糊匹配和精准匹配

(四)Switch

    排他性(单一)匹配。如果不想使用包容性,那么使用Switch,类似于js中的switch分支语句,被包裹在里面的组件会被匹配到一个,并跳出结束,常用于侧边栏,引导选项卡

属性类型作用locationstr | obj
一般我们不会给该组件设置 location 属性。

不设置: Switch组件的子组件(一般是 Route 或 Redirect)会根据当前浏览器的 location 作为匹配依据來进行路由匹配。
设置: Switch 组件的子组件会根据定义的 location 作为匹配依据

<HashRouter>
            {/* Switch类似于Js里面的Switch分支,被包裹的相当于case,总能匹配到一个,并跳出 */}

            {/* 这样能做到一个页面出出现一个,不会多个页面展示在一个页面中 */}

            <Switch>

                <Route path='/films' component={Films}></Route>

                <Route path='/home' component={Home}></Route>

            </Switch>
</HashRouter>

(五)Redirect

    重定向,如用户输入了/,见到/会指定跳转到重新定义的页面,在这里使用了exact,功能精准匹配,只有看到单独是/的才会重定向。模糊匹配,只要含有/就会响应

属性类型作用fromstring来自tostring object去向pushboolean添加历史记录exactboolean严格匹配sensitiveboolean
区分大小写

<HashRouter>
        <Route path='/films' component={Films}></Route>

        <Route path='/home' component={Home}></Route>

        {/* 模糊匹配 */}

        {/* <Redirect from='/' to='/home'/> */}

        {/* 精准匹配 */}

        <Redirect from='/' to='/home' exact/>
</HashRouter>

温馨提示:如果没有子路由的情况,建议大家配都加一个

exact

;如果有子路由,建议在子路由中加

exact

,父路由不加; 而

strict

是针对是否有反斜杠的,一般可以忽略不配置

(六)Link

    相当于a标签,在react将虚拟DOM渲染成真实DOM后,Link组件也被渲染成了a标签,常用于导航

属性类型作用tostr | obj{pathname:,search:,hash:}要跳转的路径或地址replacebool是否替换历史记录

            <li>
    
                <Link to='/films'>电影</NavLink>
    
            </li>
    
            <li>
    
            <Link to='/cimans'>影院</NavLink>
    
            </li>
    
            <li>
    
            <Link to='/home'>我的</NavLink>
    
            </li>
    

(七)NavLink

    NavLink方式相当于Link的加强版

属性类型作用tostr | obj{pathname:,search:,hash:}要跳转的路径或地址replacebool是否替换历史记录** activeClassNamestr设置选中样式,默认值为activeactiveStyleobj当元素被选中时,为此元素添加样式 exact****bool为true时,只有当导致和完全匹配class和style才会应用strictbool为true时,在确定为位置是否与当前URL匹配时,将考虑位置pathname后的斜线isActivefun**判断链接是否激活的额外逻辑的功能

            <li>
    
                <NavLink to='/films'>电影</NavLink>
    
            </li>
    
            <li>
    
                    <NavLink to='/cimans'>影院</NavLink>
    
            </li>
    
            <li>
    
                    <NavLink to='/home'>我的</NavLink>
    
            </li>
    

(八)withRouter

   将一个组件包裹进
Route

里面, 然后

react-router

的三个对象

history, location, match

就会被放进这个组件的

props

属性中.

// withRouter实现原理: 
// 将组件包裹进 Route, 然后返回
// const withRouter = () => {
//     return () => {
//         return <Route component={Nav} />
//     }
// }

// 这里是简化版
const withRouter = ( Component ) => () => <Route component={ Component }/>
//withRouter的返回值是一个新组件
    如果我们某个东西不是一个
Router

, 但是我们要依靠它去进行浏览记录的前进后退 这时候就可以使用

withRouter

,将一般组件变成路由组件。使用场景:比如点击页面的logo, 返回首页, 这时候就可以使用withRouter来做

import React, { Component } from 'react'
import {withRouter} from 'react-router-dom' //引入withRouter

class Header extends Component {

    back = ()=>{
        this.props.history.goBack()
    }

    forward = ()=>{
        this.props.history.goForward()
    }

    go = ()=>{
        this.props.history.go(-2)
    }

    render() {
        console.log('Header组件收到的props是',this.props);
        return (
            <div className="page-header">
                <h2>React Router Demo</h2>
                <button onClick={this.back}>回退</button>&nbsp;
                <button onClick={this.forward}>前进</button>&nbsp;
                <button onClick={this.go}>go</button>
            </div>
        )
    }
}

export default withRouter(Header)

//withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
//withRouter的返回值是一个新组件

三、通用Hooks

使用在5.1版本及之后,并且是函数式组件中才可以使用,使用见第四点传参时候的代码演示

(一)useHistory

获取History对象。访问history对象,进行编程式的导航

//导入

import {useHistory } from "react-router-dom"

const Home = () => {
return (

Home

)
}
const Detail = () => {

//使用

const history = useHistory()

console.log("history",history);//获取History对象

console.log("获取当前页路径",history.location.pathname);//获取当前页路径

//和下面通过js获取一致

console.log(props.location.pathname);

return (

  <-- 使用-->
   <button onClick={() => { history.push('/')}}>go home</button>
 </div>

)
}
function App() {
return (


<Router>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/detail/:id" component={Detail}/>
</Switch>
</Router>

);
}

(二)useLocation

获取Location对象。在各层组件中,轻松获取location对象。在V5.1版本之前,我们需要使用props.location。而对于更深层的组件,还需要使用

withRouter

//导入

import {

useLocation

} from "react-router-dom";

//使用

const location = useLocation ()

console.log("location",location);

(三)useParams

获取路由参数的键值对的对象,访问当前的<Route>的match.params。在V5.1版本之前,我们需要通过

props.match

获取路由参数。对于更深层的组件还需要使用高阶组件

withRouter

//设置<Route>的match.params
<Router>
<Switch>
<Route path="/:path">
<Home></Home>
</Route>
</Switch>
</Router>

//获取

let { path } = useParams();

console.log("path ",path );

(四)useRouteMatch

useRouteMatch

,接受一个

path

字符串作为参数。当参数的

path

与当前的路径相匹配时,useRouteMatch会返回match对象,否则返回null。

useRouteMatch

在对于一些,不是路由级别的组件。但是组件自身的显隐却和当前路径相关的组件时,非常有用。

比如,你在做一个后台管理系统时,网页的Header只会在登录页显示,登录完成后不需要显示,这种场景下就可以用到

useRouteMatch

const Home = () => {
return (

Home

)
}
// Header组件只会在匹配/detail/:id时出现
const Header = () => {
// 只有当前路径匹配/detail/:id时,match不为null
const match = useRouteMatch('/detail/:id')
return (
match &&
Header

)
}
const Detail = () => {
return (
Detail

)
}
function App() {
return (

<Router>

<Switch>
<Route exact path="/" component={Home}/>
<Route exact path="/detail/:id" component={Detail}/>
</Switch>
</Router>

);
}

(五)useRoutes

路由表,钩子在

useRoutes

功能上等同于,但它里面使用

JavaScript 对象

而不是

<Route>

元素来定义您的路由

  • useRoutes()的参数为数组。
  • useRoutes的返回值要么是可用于渲染路由树的有效 React 元素,要么null是不匹配的元素。
  • 嵌套路由用 children 实现。

使用useRoutes实现:

import * as React from "react";
import { useRoutes } from "react-router-dom";

function App() {
let element = useRoutes([
{
path: "/",
element: <Dashboard />,
children: [
{
path: "messages",
element: <DashboardMessages />,
},
{ path: "tasks", element: <DashboardTasks /> },
],
},
{ path: "team", element: <AboutPage /> },
]);

return element;
}

使用Routes和Route实现:

<Routes> <Route path="/" element={<Dashboard />}> <Route path="messages" element={<DashboardMessages />} /> <Route path="tasks" element={<DashboardTasks />} /> </Route> <Route path="about" element={<AboutPage />} /> </Routes>

四、路由传参

在v5.x中只有编程式的获取参数方式,在v5.1及之后增加了Hooks后,既可以用编程式的方式获取url携带的参数,也可以使用Hooks中的方法来获取(只能是函数式组件),前面一种也成为显式传参,后面两种成为隐式传参

(一)params参数

1、注册路由

//注册路由

<Route path="/details/:name/:age" component={Details}/>

2、路由跳转

//路由跳转

<Link to='/details/tom/18'}>详情</Link>

<button onClick={()=>{props.history.push('details/tom/18')}}>去详情页</button>

3、在详情页获取参数

//在详情页获取参数

console.log(props.match.params);

import { useParams } from "react-router-dom";

const params = useParams();

(二)search参数

1、注册路由

//注册路由

<Route path="/details" component={Details}/>

2、路由跳转

//路由跳转

<Link to='/details/tom/18'}>详情</Link>

<button onClick={()=>{props.history.push('details?name=tom&age=18')}}>去详情页</button>

3、在详情页获取参数

//在详情页获取参数

console.log(props.location.search);//拿到的是?id=1&age=18,

import { useParams } from "react-router-dom";

const params = useParams();拿到的是?id=1&age=18

在以上两种方式中,获取到的search是urlencoded编码字符串,需要借助query-string解析参数成对象或者自己封装一个截取的工具函数

const { search } = props.location

const { num } = qs.parse(search.slice(1))

(三)state参数

1、注册路由

//注册路由

<Route path="/details" component={Details}/>

2、路由跳转

//路由跳转

<Link to={{
    pathname:'/detils',

    state:{

            id:1,

            age:18

    }

}} > 去详情页 </Link>

<button onClick={()=>{props.history.push({

        pathname:'/details',

        state:{

            id:1,

            age:18

        }

})}}>去详情页</button>

3、在详情页获取参数

//在详情页获取参数

console.log(props.history.location.state);//{id: 1, age: 18}

import { useLocation } from "react-router-dom";

const { state } = useLocation();

console.log(state);//{id: 1, age: 18}


本文转载自: https://blog.csdn.net/m0_55173487/article/details/128618909
版权归原作者 夏*想想 所有, 如有侵权,请联系我们删除。

“react——路由”的评论:

还没有评论