后端程序员入门react笔记(七)- React路由

什么是前端路由

现代的前端页面大多是SPA(单页面应用程序), 也就是只有一个HTML页面的程序,这样用户体验好,服务器压力小,所以更受欢迎。但是一个页面可能有很多功能,比如一个页面,可能会有导航栏,有内容页。头部区域和尾部区域,那么如果是互联网刚起来的那几年,每个导航栏可能就是一个a标签,点击跳转新页面。但是这种跳转不管是对于服务器还是对于用户来说,可能都是不友好的。那么怎么能实现这样一种功能呢,就是我们点击导航栏的时候,只有内容刷新?你用点击事件固然可以这么做。但是,react-router提供了一种更简单的方式,就是以路由的方式来映射不同的组件,你操作了不同的路由,就可以调用不同的组件,实现不同的页面。

React-Router

React Router 是一个基于 React之上的强大路由库,可以实现无刷新的条件下切换显示不同的页面。

react-router主要分成了几个不同的包:

  • react-router: 实现了路由的核心功能

  • react-router-dom: 基于 react-router,加入了在浏览器运行环境下的一些功能

  • react-router-native:基于 react-router,加入了 react-native 运行环境下的一些功能

  • react-router-config: 用于配置静态路由的工具库

那这里,我们就先看我们最常用到的react-router-dom组件

react-router 6 新特性

  • v6版本移除了之前的Switch,引入了新的替代者Routes,Routes和Route配合使用,且必须用Routes包裹Route
    当url发生变化时,Routes会查看其所有子Route元素找到最佳匹配并呈现组件
    Route caseSensitive属性用于指定:匹配时是否区分大小写(默认为false)
  • component 改为 element
  • 组件传递props ,比如传递一个name:'kobe' 的属性
javascript 复制代码
//传递
<Route path='/news' element={<HomeNews name='kobe'/>}/>

//接受
function HomeNews(propsName) {
console.log(propsName);//{name: 'kobe'}
  return (
      <News>{propsName.name}</News>
  )
}
  • 路由重定向 Navigate,代替之前的Redirect

react-router-dom

react-router-dom下主要的组件有BrowserRouter,HashRouter,HashRouter,Link,NavLink,switch,redirect,我们一个个看一下

BrowserRouter

它的主要作用是为React应用程序提供客户端路由功能。它使用 HTML5 的 history API 来处理URL的变化,并根据URL的路径匹配渲染相应的组件。它通常是应用的根组件,用于包裹整个应用。

HashRouter

HashRouter和BrowserRouter作用差不多。都是用来绑定path和component的,但是两者采用的模式不一样,我们前面说过,BrowserRouter使用 HTML5 的 history API,而HashRouter是基于hash来实现的

HashRouter和BrowserRouter的区别和使用场景

HashRouter
  • 基于hash模式:页面跳转原理是使用了location.hash、location.replace;和vue router的hash模式实现一致
  • 比较丑:在域名后,先拼接/#,再拼接路径;也就是利用锚点,实现路由的跳转;如:http://www.abc.com/#/xx
BrowserRouter
  • 基于history模式:页面跳转原理是使用了HTML5为浏览器全局的history对象新增了两个API,包括 history.pushState、history.replaceState;不兼容IE9及以下版本。
  • 更加优雅: 直接拼接路径;如:http://www.abc.com/xx

Routes

Routes组件用于定义应用程序的不同路由和对应的组件。它允许我们在应用程序中定义多个路由,每个路由对应一个特定的组件,当用户访问不同的路由时,会渲染相应的组件。Routes组件还可以设置路由参数、嵌套路由、重定向等功能,帮助我们构建复杂的单页面应用程序。通过Routes组件,我们可以实现页面之间的切换和导航,提供更好的用户体验。

Route

route用于定义路由的规则,就是我这个路由对应哪个组件。其实从作用上我们也能知道,route至少接收两个参数,一个用来定义path路径,一个用来指定调用的组件component。

接下来我们看一个简单的示例,访问/a路径的时候,展示a的页面,我访问/b的时候,显示b的页面

javascript 复制代码
import React, {Component} from 'react';
import { BrowserRouter, Routes, Route } from "react-router-dom";

class App extends Component {
    render() {
        return (
            // 注意此处要用BrowserRouter包括根组件
            <BrowserRouter>

                {/*定义多个路由组件组件*/}
                <Routes>
                    <Route path="/a" element={<A/>} />
                    <Route path="/b" element={<B/>} />
                </Routes>
            </BrowserRouter>
        );
    }
}
class A extends Component {
    render() {
        return (
            <div>
                <h1>A</h1>
            </div>
        );
    }
}
class B extends Component {
    render() {
        return (
            <div>
                <h1>B</h1>
            </div>
        );
    }
}

export default App;

我们知道,当我们想实现局部刷新的时候,我们可能会使用事件来处理。react路由里面也提供了一个更加简洁的api,即link组件,这个组件用于创建导航链接。它会生成一个 标签,并处理点击事件以避免浏览器重新加载页面。你可以使用 to属性和route的path属性绑定来实现这个功能。我们来试一下

javascript 复制代码
render() {
        return (
            // 注意此处要用BrowserRouter包括根组件,可以提到index.js里面包裹App标签
            <BrowserRouter>

                {/*这是导航区域*/}
                <ul>
                    <li>
                        <Link to="/a">我是a</Link>
                    </li>
                    <li> <Link to="/b">我是b</Link></li>
                </ul>

                {/*定义多个路由组件组件 展示组件的返回值*/}
                <Routes>
                    <Route path="/a" element={<A/>} />
                    <Route path="/b" element={<B/>} />
                </Routes>
            </BrowserRouter>
        );
    }

link的to属性看定义为一个对象,相关属性如下

  • pathname: 表示要链接到的路径的字符串。
  • search: 表示查询参数的字符串形式。
  • hash: 放入网址的 hash,例如 #a-hash。
  • state: 状态持续到 location。通常用于隐式传参(埋点),可以用来统计页面来源
javascript 复制代码
<Link to={{
                            pathname: '/a',
                            search: '?id=1',
                            hash: '#someHash',
                            state: { fromWechat: true }
                        }}>我是a</Link>

可以看做 一个特殊版本的 Link,当它与当前 URL 匹配时,为其渲染元素添加样式属性。相关属性如下

  • exact: 如果为 true,则仅在位置完全匹配时才应用 active 的类/样式。
  • strict: 当为 true,要考虑位置是否匹配当前的URL时,pathname 尾部的斜线要考虑在内。
  • location 接收一个location对象,当url满足这个对象的条件才会跳转
  • isActive: 接收一个回调函数,只有当 active 状态变化时才能触发,如果返回false则跳转失败
    最简单的例子就是当路由是/a的时候,会给绑定当前路由的a标签添加一个active的类属性。

将一个路由组件重定向到某个新地址

javascript 复制代码
<Route path="/c" element={<Navigate to="/a"/>} />

路由嵌套

我们知道,在现实中,写的路由大部分都是有统一前缀的,那么我们就要在前缀的基础上写路由,而不是所有的路由都把前缀带上,那么我们怎么写呢,我们来看一下

javascript 复制代码
import React, {Component} from 'react';
import {Routes, Route,Link } from "react-router-dom";

class App extends Component {

    A=()=>{
        return <h1>我是a</h1>
    }

    B=()=>{
        return <h1>我是B</h1>
    }
    render() {
        return (
            // 注意此处要用BrowserRouter包括根组件,可以提到index.js里面包裹App标签
            <div>
                <ul>
                    <li><Link to="/h5/a">我是a</Link></li>
                    <li> <Link to="/h5/b">我是b</Link></li>
                </ul>
                {/*在这里配置前缀*/}
                <Routes>
                    <Route path="/h5/*" >
                        <Route path="a" element={this.A()}></Route>
                        <Route path="b" element={this.B()}></Route>
                    </Route>
                </Routes>
            </div>
        );
    }
}
export default App;
  • 路由的集中管理
    我们看到,在代码里面写满了路由,明显是很low的,那么我们能不能把路由集中管理起来呢,比如我新建了一个路由文件,叫Route.jsx
javascript 复制代码
import {useRoutes} from "react-router-dom";
import A from "../A/A"
import B from "../B/B"

const DefineRoute=()=>{
    return useRoutes(
        [
            // 单路由
            {
                path:"/",
                element:<div>Home</div>
            },
            //嵌套路由
            {
                path:"/h5",
                children:[
                    {
                        path:"a",
                        element:<A/>
                    },
                    {
                        path:"b",
                        element:<B/>
                    }
                ]
            }
        ]
    )
}

export default DefineRoute
  • 完毕之后我需要在使用的地方把它渲染出来,比如我在index.js里面渲染,完成之后,即可使用路由
javascript 复制代码
import DefineRoute from "./components/Route/Route"
const app= <BrowserRouter><DefineRoute /><App/></BrowserRouter>

路由参数

前面我们说了很多路由相关的基础知识呢,那么最重要的问题来了,路由的参数我们怎么获取?我们来看一下

我们改一下路由b

javascript 复制代码
{
   path:"b/:age/:name",
   element:<B/>
}
  • 修改b组件
javascript 复制代码
import React from 'react';
import { useParams,useSearchParams } from "react-router-dom";


function B() {
    const [search,setsearch] = useSearchParams()//返回search参数 和 更新search参数的函数
    const {age,name}= useParams();
    console.log(search.get("title"))    // ['123']
    console.log(search.getAll("title"))    // ['123']
    return (
        <div>
            <h1>B</h1>
            <h1>age:{age}</h1>
            <h1>name:{name}</h1>
            <button onClick={()=>setsearch('id=2&title=更新search')}>点我更新search参数</button>
        </div>
    );
}

export default B;

相关参考

react-router 6 新特性总结
react-route6 封装

相关推荐
蜗牛快跑2135 分钟前
面向对象编程 vs 函数式编程
前端·函数式编程·面向对象编程
Dread_lxy6 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
huangkj-henan6 分钟前
DA217应用笔记
笔记
Young_202202027 分钟前
学习笔记——KMP
笔记·学习
秀儿还能再秀40 分钟前
机器学习——简单线性回归、逻辑回归
笔记·python·学习·机器学习
WCF向光而行1 小时前
Getting accurate time estimates from your tea(从您的团队获得准确的时间估计)
笔记·学习
涔溪1 小时前
Ecmascript(ES)标准
前端·elasticsearch·ecmascript
榴莲千丞1 小时前
第8章利用CSS制作导航菜单
前端·css
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与1 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts