20230602----重返学习-React路由

这篇具有很好参考价值的文章主要介绍了20230602----重返学习-React路由。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

day-083-eighty-three-20230602-React路由

React路由

  • 新版的是react-router-dom是6版本,而旧版的是5版本。

  • 基于前端路由实现SPA单页面应用,其核心在于:构建路由表(构建路由匹配机制)。

    1. 每一次路由切换(包含刚开始第一次渲染页面),都会拿当前的地址(或者哈希值)去路由表中进行查找匹配,找到相匹配的组件。
      • 包含刚开始第一次渲染页面
    2. 找到的组件放在指定的容器中渲染。

划分路由

  • 常见的路由划分方式:

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LqE0rl0A-1685721346336)(./如何划分路由.jpg)]

    • 基础页面-基本由路由控制。

      • /user 登录注册所在页。
        • /user/login 登录页。
        • /user/register 注册页。
      • / 主页-首页所在的页面,除登录注册页与404页面。
        • /home 首页。
          • home/watch 监控。
          • /home/woker 控制台。
          • /home/message 消息。
        • /categroy 分类管理。
        • /personal 个人中心。
      • * 404页面。
    • 基础页面-由路由与选项卡控制。

      • / 默认页,重定向到/home
      • /login 登录注册所在页。
        1. 登录页与登录页是使用tag组件进行切换的。
      • /home 主页-首页所在的页面。
        • /home/welcome 首页-欢迎页。
        • home/categroy 分类管理。
        • /home/personal 个人中心。
      • * 404页面。
    • 扁平化路由页面-全部一级路由。

      • / 默认页,重定向到/home
      • /login 登录注册所在页。
      • /home 首页。
      • /categroy 分类管理。
      • /personal 个人中心。
      • * 404页面。
        1. 在二级及以上的路由都可以跳转到404页。
        2. 用户输入错误地址,可以到404页。
  • 一般一个应用,路由只有三层。最多只要5级路由。

  • 一级路由中根路径/要挪到末尾不加exact属性,而二级路由根路径则是根路径放前面加exact属性。

react-router-dom版本V5

  • react-router-dom的V5版本:
    1. 和vue-router不同,没有单独的路由表,需要把路由匹配机制,写在指定组件的特定位置。

      • 特定位置:那一块需要根据不同地址渲染不同组件,就把匹配机制写在那。

        import { HashRouter, BrowserRouter, Route, Switch, Redirect } from 'react-router-dom'
        
    2. 视图入口主文件定义一级路由。

      // 1. 导入路由组件HashRouter,BrowserRouter,StaticRouter。
      import {
        HashRouter,
        BrowserRouter,
        StaticRouter,
        Route,
        Switch,
        Redirect,
      } from "react-router-dom";
      
      
      // 1.5. 导入一级路由需要的组件。
      import BasicLayout from "./layout/BasicLayout";
      import UserLayout from "./layout/UserLayout";
      import Error from "./layout/Error";
      
      // 2. 用路由组件把业务组件包起来。
      <HashRouter>
        {/* 4. 只匹配一个组件,如果符合条件,就停止匹配。 */}
        <Switch>
          {/* 3. 定义路由匹配机制。每一条匹配条件,就写一个Route组件。 */}
          {/* <Route exact path="/" component={BasicLayout}></Route> */}
          <Route path="/user" component={UserLayout}></Route>
          {/* <Route path="*" component={Error}></Route> */}
          {/* <Route component={Error}></Route> */}
      
          <Route path="/404" component={Error}></Route>
      
          <Route path="/" component={BasicLayout}></Route>
      
          {/* 5. 定义重定向。 */}
          {/* <Redirect from="*" to="/404"></Redirect> */}
          <Redirect to="/404"></Redirect>
          {/* 6. 把`/`移动到后方,这个404已经不会重定向了,但习惯于把它放到后方用于提示。 */}
      
        </Switch>
      </HashRouter>
      
      1. 导入路由组件HashRouter,BrowserRouter,StaticRouter中其中一个。以及路由匹配组件Route,以及一个路由重定向组件Redirect,以及仅匹配单个路由组件Switch。
      2. 用路由组件把业务组件包起来。
      3. 定义路由匹配机制。每一条匹配条件,就写一个Route组件。
        • Route组件的默认是宽松匹配,只要路由地址包含了Route组件的path属性,就默认匹配上了。
        • Route组件的exact属性可以让路由被精准地匹配,只有路由地址与Route组件的path属性一模一样才算匹配成功。
      4. 使用Switch组件把Route组件组包裹起来,让Route组件组中只匹配一个组件,如果符合条件,就停止匹配。
      5. 使用Redirect组件定义重定向。
      • fang/f20230602/route基础/src/App.jsx

        import React from "react";
        // 1. 导入路由组件HashRouter,BrowserRouter,StaticRouter。
        import {
          HashRouter,
          BrowserRouter,
          StaticRouter,
          Route,
          Switch,
          Redirect,
        } from "react-router-dom";
        /* //{HashRouter,BrowserRouter,StaticRouter,: 控制使用何种路由切换方式,是Hash路由还是History路由。
          - Switch组件:控制如果某一个Route匹配成功,则不再继续向下匹配了!
          - Redirect:重定向,语法和Route类似,只不过其不需要component,而是基于to来指定重定向后的地址,并且基于from!
          - Route:构建路由的匹配机制。
            - path 匹配地址。
              - 当路由切换完毕或页面刷新,会拿最新的路由地址,和ROute中的path进行匹配;找到匹配项后,把对应的component组件,在此位置进行渲染!
            - component 需要渲染的组件。
        */
        
        // 4. 导入一级路由需要的组件。
        import BasicLayout from "./layout/BasicLayout";
        import UserLayout from "./layout/UserLayout";
        import Error from "./layout/Error";
        
        const App = function App() {
          return (
            // 2. 用路由组件把业务组件包起来。
            <HashRouter>
              {/* 4. 只匹配一个组件,如果符合条件,就停止匹配。 */}
              <Switch>
                {/* 3. 定义路由匹配机制。每一条匹配条件,就写一个Route组件。 */}
                {/* <Route exact path="/" component={BasicLayout}></Route> */}
                <Route path="/user" component={UserLayout}></Route>
                {/* <Route path="*" component={Error}></Route> */}
                {/* <Route component={Error}></Route> */}
        
                <Route path="/404" component={Error}></Route>
        
                <Route path="/" component={BasicLayout}></Route>
        
                {/* 5. 定义重定向。 */}
                {/* <Redirect from="*" to="/404"></Redirect> */}
                <Redirect to="/404"></Redirect>
                {/* 6. 把`/`移动到后方,这个404已经不会重定向了,但习惯于把它放到后方用于提示。 */}
        
              </Switch>
            </HashRouter>
          );
        };
        export default App;
        
      • HashRouter组件/BrowserRouter组件:控制使用何种路由切换方式,是 Hash路由 还是 History路由

      • Switch组件:控制如果某一个Route匹配成功,则不再继续向下匹配了。

      • Redirect组件:重定向,语法和Route类似,只不过其不需要component,而是基于 to 来指定重定向后的地址,并且基于from来代替path

      • Route组件:构建路由的匹配机制。

        • path:匹配地址。
          • 当路由切换完毕或页面刷新,会拿最新的路由地址,和Route中的path进行匹配;找到匹配项后,把对应的component组件在此位置进行渲染!

            路由地址 path值 是否匹配 是否精准匹配
            / /
            / /user
            /user /
            /user /user
            /user2 /user
            /user/login /user
          • 默认是按照整体进行匹配的(一个完整的/xxx算是一个整体),如果路由地址中有一到多个整体,其中有一部分整体path值一致,则说明匹配,反之是不匹配!/也算一个整体,所以默认情况下/xxx都会匹配/

        • exact:开启精准匹配,要求路由地址必须和path一模一样才算匹配成功。
          • 一般放在path="/",或者其它组件上。
        • component:需要渲染的组件。
    3. 在一级路由对应的组件中配置对应的二级路由信息。

      1. 引入Switch, Route, Redirect。
      2. 引入需要用的二级路由组件。
      3. 使用Switch, Route, Redirect配置某个一级路由下的二级路由信息。
      // 1. 引入Switch, Route, Redirect。
      import { Switch, Route, Redirect } from "react-router-dom";
      // 2. 引入需要用的二级路由组件
      import Login from "@/views/Login";
      import Register from "@/views/Register";
      
      {/* 3. 使用Switch, Route, Redirect配置某个一级路由下的二级路由信息。 */}
      <Switch>
        <Redirect exact from="/user" to="/user/login" />
        <Route path="/user/login" component={Login} />
        <Route path="/user/register" component={Register} />
        <Redirect to="/404" />
      </Switch>
      
      1. 一级路由对应的组件一般在React阶段/day0602/src「router基础运用」/layout这个目录中。
      2. 一级路由对应组件的根目录一般用重定向组件Redirect的exact属性来指定精准匹配及重定向到该一级路由对应组件的某个二级路由上。
      • 代码:
        • React阶段/day0602/src「router基础运用」/layout/UserLayout.jsx 有二级路由。

          import React from "react";
          import { Tabs } from "antd";
          import styled from "styled-components";
          import backgroundImg from "@/assets/images/background.svg";
          import logo from "@/assets/images/logo.svg";
          // 1. 引入Switch, Route, Redirect。
          import { Switch, Route, Redirect } from "react-router-dom";
          
          // 2. 引入需要用的二级路由组件
          import Login from "@/views/Login";
          import Register from "@/views/Register";
          
          /* 组件样式 */
          const UserLayoutStyle = styled.div`
            position: relative;
            height: 100%;
            background: url(${backgroundImg}) no-repeat;
            background-size: 100%;
          
            .content {
              position: absolute;
              top: 100px;
              left: 50%;
              margin-left: -165px;
              width: 330px;
            }
          
            .header {
              .title {
                display: flex;
                justify-content: center;
                align-items: center;
                line-height: 44px;
                font-size: 33px;
                font-weight: normal;
          
                img {
                  margin-right: 10px;
                  width: 44px;
                  height: 44px;
                }
              }
          
              .subtitle {
                margin: 12px 0 40px 0;
                text-align: center;
                font-size: 14px;
                color: rgba(0, 0, 0, 0.45);
              }
            }
          
            .ant-tabs {
              margin-bottom: 10px;
          
              .ant-tabs-nav {
                &:before {
                  border-bottom-color: #ddd;
                }
              }
          
              .ant-tabs-tab {
                padding: 0 10px;
                font-size: 16px;
                line-height: 40px;
              }
            }
          `;
          
          const UserLayout = function UserLayout() {
            // Tab页卡的数据
            const tabItem = [
              {
                label: `用户登录`,
                key: "login",
              },
              {
                label: `用户注册`,
                key: "register",
              },
            ];
          
            return (
              <UserLayoutStyle>
                <div className="content">
                  <div className="header">
                    <h1 className="title">
                      <img src={logo} alt="" />
                      <span>Ant Design</span>
                    </h1>
                    <p className="subtitle">
                      Ant Design 是西湖区最具影响力的 Web 设计规范
                    </p>
                  </div>
                  <Tabs centered defaultActiveKey="login" items={tabItem} />
                  {/* 登录/注册二级路由的位置 */}
          
                  {/* 3. 使用Switch, Route, Redirect配置某个一级路由下的二级路由信息。 */}
                  <Switch>
                    <Redirect exact from="/user" to="/user/login" />
                    <Route path="/user/login" component={Login} />
                    <Route path="/user/register" component={Register} />
                    <Redirect to="/404" />
                  </Switch>
                </div>
              </UserLayoutStyle>
            );
          };
          export default UserLayout;
          
        • React阶段/day0602/src「router基础运用」/layout/BasicLayout.jsx 有二级路由,需要配置。

          import { useState } from "react";
          import { Menu, Button } from "antd";
          import {
            HomeOutlined,
            ClusterOutlined,
            UserOutlined,
            MenuUnfoldOutlined,
            MenuFoldOutlined,
          } from "@ant-design/icons";
          import styled from "styled-components";
          import logo from "@/assets/images/logo.svg";
          import avatar from "@/assets/images/touxiang.png";
          
          // 1. 引入Switch, Route, Redirect。
          import { Switch, Route, Redirect } from "react-router-dom";
          
          // 2. 引入需要用的二级路由组件
          import Home from "@/views/Home";
          import Category from "@/views/Category";
          import Personal from "@/views/Personal";
          
          /* 组件样式 */
          const BasicLayoutStyle = styled.div`
            height: 100%;
            overflow: hidden;
          
            .header {
              box-sizing: border-box;
              padding: 0 15px;
              height: 48px;
              background: #001529;
              display: flex;
              justify-content: space-between;
              align-items: center;
          
              .logo,
              .info {
                line-height: 48px;
                font-size: 18px;
                color: #fff;
                display: flex;
                align-items: center;
          
                img {
                  margin-right: 10px;
                  width: 35px;
                  height: 35px;
                }
              }
          
              .info {
                font-size: 14px;
          
                img {
                  width: 30px;
                  height: 30px;
                }
              }
            }
          
            .content {
              height: calc(100% - 48px);
              display: flex;
          
              .menu-box {
                height: 100%;
                background: #001529;
          
                .ant-btn {
                  margin-left: 4px;
                  background: transparent;
                  box-shadow: none;
                }
          
                .ant-menu-item {
                  padding: 0 24px;
                }
          
                .ant-menu-inline-collapsed {
                  .ant-menu-item {
                    padding: 0 28px;
                  }
                }
              }
          
              .view-box {
                box-sizing: border-box;
                padding: 15px;
                height: 100%;
                flex-grow: 1;
          
                .component {
                  height: 100%;
                  overflow-y: auto;
                  overflow-x: hidden;
                  background: #fff;
                }
              }
            }
          `;
          
          const BasicLayout = function BasicLayout() {
            // 左侧Menu的数据
            const menuItem = [
              {
                key: "home",
                label: "控制面板",
                icon: <HomeOutlined />,
              },
              {
                key: "category",
                label: "分类管理",
                icon: <ClusterOutlined />,
              },
              {
                key: "personal",
                label: "个人中心",
                icon: <UserOutlined />,
              },
            ];
          
            // 定义状态
            let [collapsed, setCollapsed] = useState(false);
          
            return (
              <BasicLayoutStyle>
                <div className="header">
                  <h2 className="logo">
                    <img src={logo} alt="" />
                    Ant Design
                  </h2>
                  <div className="avatar">
                    <p className="info">
                      <img src={avatar} alt="" />
                      海贼王-路飞
                    </p>
                  </div>
                </div>
                <div className="content">
                  <div className="menu-box">
                    <Button
                      type="primary"
                      onClick={() => {
                        setCollapsed(!collapsed);
                      }}
                    >
                      {collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
                    </Button>
                    <Menu
                      mode="inline"
                      theme="dark"
                      items={menuItem}
                      defaultSelectedKeys={["home"]}
                      inlineCollapsed={collapsed}
                    />
                  </div>
                  <div className="view-box">
                    <div className="component">
                      {/* 主页的二级路由 */}
          
                      {/* 3. 使用Switch, Route, Redirect配置某个一级路由下的二级路由信息。 */}
                      <Switch>
                        <Redirect exact from="/" to="/home" />
                        <Route path="/home" component={Home} />
                        <Route path="/category" component={Category} />
                        <Route path="/personal" component={Personal} />
                        <Redirect to="/404" />
                      </Switch>
                    </div>
                  </div>
                </div>
              </BasicLayoutStyle>
            );
          };
          export default BasicLayout;
          
        • React阶段/day0602/src「router基础运用」/layout/Error.jsx 无二级路由,不需要配置。

          import React from "react";
          import { Button, Empty } from "antd";
          import styled from "styled-components";
          
          /* 组件的样式 */
          const ErrorStyle = styled.div`
            height: 100%;
            overflow: hidden;
          
            .ant-empty {
              position: relative;
              top: 100px;
            }
          `;
          
          const Error = function Error() {
            return (
              <ErrorStyle>
                <Empty description={<span>很遗憾,您访问的页面不存在!</span>}>
                  <Button type="primary">返回首页</Button>
                </Empty>
              </ErrorStyle>
            );
          };
          export default Error;
          
    4. 在二级路由对应的组件中配置对应的三级路由信息。

      1. 引入Switch, Route, Redirect。
      2. 引入需要用的二级路由组件。
      3. 使用Switch, Route, Redirect配置某个二级路由下的三级路由信息。
      // 1. 引入Switch, Route, Redirect。
      import { Switch, Route, Redirect } from "react-router-dom";
      
      // 2. 引入需要用的二级路由组件。
      import Watch from "./home/Watch";
      import Worker from "./home/Worker";
      import Message from "./home/Message";
      
            {/* 3. 使用Switch, Route, Redirect配置某个二级路由下的三级路由信息。 */}
            <Switch>
              <Redirect exact from="/home" to="/home/watch" />
              <Route path="/home/watch" component={Watch} />
              <Route path="/home/worker" component={Worker} />
              <Route path="/home/message" component={Message} />
              <Redirect to="/404" />
            </Switch>
      
      1. 二级路由及二级路由以下对应的组件一般在React阶段/day0602/src「router基础运用」/views这个目录中。
      2. 一级路由对应组件的根目录一般用重定向组件Redirect的exact属性来指定精准匹配及重定向到该一级路由对应组件的某个二级路由上。
      import React from "react";
      import styled from "styled-components";
      
      // 1. 引入Switch, Route, Redirect。
      import { Switch, Route, Redirect } from "react-router-dom";
      
      // 2. 引入需要用的二级路由组件。
      import Watch from "./home/Watch";
      import Worker from "./home/Worker";
      import Message from "./home/Message";
      
      /* 组件样式 */
      const HomeStyle = styled.div`
        padding: 10px;
      
        .nav-box {
          display: flex;
          border-bottom: 1px solid #eee;
      
          a {
            padding: 0 20px;
            line-height: 40px;
            font-size: 15px;
            color: #000;
          }
        }
      `;
      
      const Home = function Home() {
        return (
          <HomeStyle>
            <nav className="nav-box">
              <a href="#/home/watch">数据监控</a>
              <a href="#/home/worker">工作台</a>
              <a href="#/home/message">消息中心</a>
            </nav>
            {/* 首页的三级路由 */}
            {/* 3. 使用Switch, Route, Redirect配置某个二级路由下的三级路由信息。 */}
            <Switch>
              <Redirect exact from="/home" to="/home/watch" />
              <Route path="/home/watch" component={Watch} />
              <Route path="/home/worker" component={Worker} />
              <Route path="/home/message" component={Message} />
              <Redirect to="/404" />
            </Switch>
          </HomeStyle>
        );
      };
      export default Home;
      

react-router创建流程

  1. 规划好路由方案。
  2. 规划文件结构。
    • 文件结构示例:
      • fang/f20230602/src/api 处理接口相关的。
      • fang/f20230602/src/assets 放置静态资源的。
        • fang/f20230602/src/assets/images 静态资源-图片放置的地方。
        • fang/f20230602/src/assets/reset.min.css 样式重置文件。
      • fang/f20230602/src/views 放各业务组件,一般是二级路由组件及以下的路由组件。
        • fang/f20230602/src/views/Login.jsx 登录页。
      • fang/f20230602/src/layout 放置布局模块,一般是一级路由页面。
        1. 404报错页也可以不放在这,因为太简单了。
          • 不过个人建议放在这里,那么这个布局里就全都放置了一级路由,组件逻辑更统一。
        • fang/f20230602/src/layout/UserLayout.jsx 登录注册布局。
        • fang/f20230602/src/layout/BasicLayout.jsx 首页所在页。
        • fang/f20230602/src/layout/Error.jsx 404错误页。
      • fang/f20230602/src/index.jsx 程序入口主文件,主要用来处理程序功能。
      • fang/f20230602/src/index.less 全局样式的less文件。
      • fang/f20230602/src/App.jsx 视图入口主文件,项目根组件。处理视图及路由。一般用来匹配一级路由。
  3. 在视图入口主文件中匹配一级路由。

react-router-dom文件

  • 是通过插件react-router-dom来导入的。

    import {
      HashRouter,
      BrowserRouter,
      StaticRouter,
      Route,
      Switch,
      Redirect,
    } from "react-router-dom";
    
  • react-router-dom常见组件:

    • 路由组件:
      • HashRouter:哈希路由组件,控制内部的组件模式是Hash路由。
      • BrowserRouter:浏览器路由组件,控制内部的组件模式是History浏览器路由。
        • 也叫历史路由。
      • StaticRouter:静态路由组件,这个是后端渲染时用的。
    • Route:构建路由的匹配机制。
      • path 匹配地址。
        • 当路由切换完毕或页面刷新,会拿最新的路由地址,和ROute中的path进行匹配;找到匹配项后,把对应的component组件,在此位置进行渲染!
      • component 需要渲染的组件。
    • Switch:控制如果某一个Route匹配成功,则不再继续向下匹配了!
    • Redirect:重定向,语法和Route类似,只不过其不需要component,而是基于to来指定重定向后的地址,并且基于from!

路由统一管理

  1. 创建一个文件夹,用于存放路由相关的信息。

    • fang/f20230602/src/router 用于存放路由相关的信息,以后路由相关的处理,统一放在这里。
      • fang/f20230602/src/router/routes.js 用于存放总体的路由信息表。

        1. 路由表中的每一项都是对象,参照着vue-router的规则来。
          • 每一项的属性:
            • path:‘’ 需要匹配的地址,也是redirect模式下的from。

            • name:undefined 路由名字。

            • component:null 路由匹配后需要渲染的组件。

            • render:undefined 某些情况下,传递的不是component而是render。

            • exact:undefined 是否开启精准匹配。

            • redirect:undefined 设置redirect后,则开启重定向模式,redirect存储的是重定向后的地址。

            • meta:{} 路由元信息,即我们自己给每一个路由设置的自定义信息。

            • children:undefined 子路由信息,如果有子路由,则值是一个数组。

        /* //
        - 路由表中的每一项都是对象,参照着vue-router的规则来。
          - 每一项的属性:
            - path:'' 需要匹配的地址,也是redirect模式下的from。
            - name:undefined 路由名字。
            - component:null 路由匹配后需要渲染的组件。
            - render:undefined 某些情况下,传递的不是component而是render。
            - exact:undefined 是否开启精准匹配。
        
            - redirect:undefined 设置redirect后,则开启重定向模式,redirect存储的是重定向后的地址。
            - meta:{} 路由元信息,即我们自己给每一个路由设置的自定义信息。
            - children:undefined 子路由信息,如果有子路由,则值是一个数组。
        */
        
        import UserLayout from "@/layout/UserLayout";
        import Login from "@/views/Login";
        import Register from "@/views/Register";
        import Error from "@/layout/Error";
        
        import BasicLayout from "@/layout/BasicLayout";
        import Home from "@/views/Home";
        import Category from "@/views/Category";
        import Personal from "@/views/Personal";
        
        import Watch from "@/views/home/Watch";
        import Worker from "@/views/home/Worker";
        import Message from "@/views/home/Message";
        
        // User下的二级路由:
        const userChildren = [
          {
            path: "/user",
            exact: true,
            redirect: "/user/login",
          },
          {
            path: "/user/login",
            name: "login",
            meta: { title: "用户登录" },
            component: Login,
          },
          {
            path: "/user/register",
            name: "register",
            meta: { title: "用户注册" },
            component: Register,
          },
        ];
        
        // Home(控制面板)下的三级路由
        const homeChildren = [
          {
            path: "/home",
            exact: true,
            redirect: "/home/watch",
          },
          {
            path: "/home/watch",
            name: "watch",
            meta: { title: "数据监控" },
            component: Watch,
          },
          {
            path: "/home/worker",
            name: "worker",
            meta: { title: "工作台" },
            component: Worker,
          },
          {
            path: "/home/message",
            name: "message",
            meta: { title: "消息中心" },
            component: Message,
          },
        ];
        
        // Basic-主页下的二级路由。
        const basicChildren = [
          {
            path: "/",
            exact: true,
            redirect: "/home",
          },
          {
            path: "/home",
            name: "home",
            meta: { title: "控制面板" },
            component: Home,
            children: homeChildren,
          },
          {
            path: "/category",
            name: "category",
            meta: { title: "分类管理" },
            component: Category,
          },
          {
            path: "/personal",
            name: "personal",
            meta: { title: "个人中心" },
            component: Personal,
          },
        ];
        
        // 一级路由:
        const routes = [
          {
            path: "/user",
            name: "user",
            meta: {},
            component: UserLayout,
            children: userChildren,
          },
          {
            path: "/404",
            name: "error",
            meta: { title: "404错误页" },
            component: Error,
          },
          {
            path: "/",
            name: "basic",
            meta: {},
            component: BasicLayout,
            children: basicChildren,
          },
        ];
        export default routes;
        
      • fang/f20230602/src/router/index.jsx 创建一个路由统一管理组件,用于浅遍历出一个路由数组表示的路由信息。类似vue-route。

        import { Switch, Redirect, Route } from "react-router-dom";
        import routes from "./routes";
        
        const routesArray = routes;
        // 根据传递的name,获取需要迭代的路由表。
        const queryRoutesByName = (name, routes = routesArray) => {
          if (!name) {
            return routes;
          }
          let arr = [];
          const next = (routes) => {
            routes.forEach((item) => {
              //此项是匹配的。
              if (item.name === name) {
                arr = item.children || [];
                return;
              }
              //如果此项不配,并且具备children,则递归深入查找。
              if (item.children) {
                next(item.children);
              }
            });
          };
          next(routes);
          return arr;
        };
        
        // 通用的路由匹配机制。
        //
        // 如果传入一个name,就根据name来对路由表进行深度查找并返回同name属性下的children。如果没传入name或空字符串,则对一级路由进行校验。
        
        const RouterView = function RouterView({ name, routes = routesArray }) {
          console.log(`mememe`);
          let arr = queryRoutesByName(name, routes);
          if (!arr || arr.length === 0) {
            return null;
          }
          // console.log(`路由表`);
          return (
            <Switch>
              {arr.map((item, index) => {
                let { path, component, render, exact, redirect } = item;
        
                // 重定向的规则:
                if (redirect) {
                  let props = {};
                  if (exact) {
                    props.exact = true;
                  }
                  if (path) {
                    props.path = path;
                  }
                  props.to = redirect;
                  // console.log('props',props);
                  return <Redirect key={index} {...props}></Redirect>;
                }
        
                // 正常匹配的规则;
                let props = {};
                if (exact) {
                  props.exact = true;
                }
                props.path = path;
                typeof render === "function"
                  ? (props.render = render)
                  : (props.component = component);
                return <Route key={index} {...props}></Route>;
              })}
              <Redirect to="/404"></Redirect>
            </Switch>
          );
        };
        RouterView.defaultProps = {
          name: "",
        };
        export default RouterView;
        
  2. 在业务组件中需要用到路由表的地方,引入路由统一管理组件,并设置它的name。此时路由统一管理组件会浅遍历出对应name的路由下的各个子节点。

路由跳转

  1. 引入Link组件或NavLink组件。

    import {Link,NavLink} from 'react-router-dom'
    
    • Link与NavLink都是实现路由切换的方式。

      <Link to="要跳转的路由地址">渲染的内容</Link>
      
      • 属性

        • to属性值是字符串与对象
          • to=“/home/watch”
          • to={{pathname:‘/home/watch’,}}
        • replace 如果设置这个属性,则本次路由跳转是替换现有的历史记录,而不是新增记录。
      • 渲染完成的结果还是a标签。

        • 但是它会根据当前路由的模式,自动设置a标签的href属性值。
          • 假设为:<Link to="/home/watch">数据监控</Link>
          • 哈希路由 href='#/home/watch'
          • History路由 href='/home/watch' 在内部点击a标签的时候,阻止了a标签的默认行为,转而基于HistoryAPI实现路由的跳转。
      • NavLink其语法和Link基本上一致,主要区别是:

        • 会拿当前路由的地址和to要跳转的地址进行匹配,默认是非精准匹配,不过我们可以设置exact让其变为精准匹配。
        • 和那一项匹配了,就给当前项设置一个叫做active的样式类。
          • 可以基于activeClassName 修改匹配的样式类名。
          • 也可以直接基于className或style或activeStyle设置选中的样式。
        • 这样我们就可以给当前选中的项,设置选中样式了!
  2. 在业务组件中使用Link组件或NavLink组件。文章来源地址https://www.toymoban.com/news/detail-469246.html

进阶参考

到了这里,关于20230602----重返学习-React路由的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 20230428----重返学习-vue项目

    配置开发服务器 如果没有后端接口,可以直接通过浏览器控制台看到别人网站的接口。 Shift+Control+I打开浏览器控制台,点击Network查看网络请求,点击Fetch/XHR,查看当前页面发送的请求。 触发请求,可以看到浏览器向别人的后端发送的请求及请求信息。 复制一下请求路径和

    2024年02月01日
    浏览(35)
  • 20230406----重返学习-AJAX

    AJAX全称async javascript and xml。 以前的数据一般是xml,现在大多是json。 AJAX不是一种新的技术,而一个与后端通信的方式。 特色: 异步获取数据,局部更新页面。 数据渲染 服务器渲染 客户端渲染----(局部更新页面) 服务器渲染 [外链图片转存失败,源站可能有防盗链机制,建议将图

    2023年04月10日
    浏览(35)
  • 20230620----重返学习-移动端事件处理-响应式

    移动端的事件处理 移动端事件处理 PC端主要以: 鼠标事件 、 键盘事件 、 资源加载事件 、 动画事件 等事件为主。 其中 click 在 PC端 是 点击事件 ! 移动端主要以: 手指事件 ( 单手指 和 多手指 )、 资源加载事件 、 动画事件 等为主。 其中, click 在 移动端 是 单击事件

    2024年02月09日
    浏览(36)
  • 【React Native】学习记录(二)——路由搭建和常见的开发技巧

    在开发过程中发现,两个模拟器都不能输入中文,所以需要配置一下。 先说一下安卓,在弹出的输入框中查看设置,设置一下对应的 languages 即可: 在苹果模拟器中,跟苹果手机一样,打开设置,然后打开通用,同样设置语言: 我在这里走了弯路,去了另一个库…,路由文

    2024年02月15日
    浏览(47)
  • 20230401----重返学习-冒泡相关事件-拖拽-放大镜

    mouseenter/mouseleave与mouseover/mouseout mouseover/mouseout 有冒泡,忽略层级之间的关系 mouseenter/mouseleave 没冒泡,不会忽略层级之间的关系 事件委托 事件委托: 也叫事件代理,将绑定的事件委托给祖先元素,祖先元素监听事件,并利用e.target来分配给当前元素 原理是: 事件冒泡机制 事

    2023年04月08日
    浏览(41)
  • 20230728----重返学习-跨域-模块化-webpack初步

    跨域 为什么要跨域? 浏览器为了安全,不能让我们的html文件可以随意引用别的服务器中的文件,只允许我们的html或js文件中,请求我们自己服务器。这个就是浏览器的同源策略。 因为我们的网页是一个html文件,这个html是在一个域名里的。而这个html会引用各种文件,如图片

    2024年02月15日
    浏览(48)
  • 20230623----重返学习-vue-cli脚手架

    Vue工程化处理工具之 : @vue/cli 脚手架的本质:基于webpack实现项目的打包部署; vue/cli 安装和使用 可选择当前配置项 文件地址在:C:Users当前电脑用户名.vuerc。 如:C:Usersfangc.vuerc 文件目录 package.json 目录: scripts:npm可执行命令 serve命令: vue-cli-service 是Vue脚手架内部封装的

    2024年02月10日
    浏览(65)
  • 20230711----重返学习-组件缓存-图片上传-富文编辑器-鉴权处理

    keep-alive组件的使用 keep-alive组件的原理 图片上传流程 点击上传图片后,把图片发送给服务器。 服务器返回一个相对或绝对地址。 提交时,把图片地址与其余表单数据一起传递给服务器。 el-upload组件 图片上传分为两步: 选取图片 规则限制:类型、大小… multiple 是否支持多

    2024年02月16日
    浏览(44)
  • 20230619----重返学习-图片缩略图幻灯片-插件封装的步骤-NativeApp与WebApp

    总体思路 整理思路。 所有的结构都包在一个盒子中。盒子里有两层内容: 盒子宽高由前端根据设计稿来定。 盒子宽高应具体到px,以便内部使用百分比进行布局。 一层是封面,用于展示播放时长和视频主图。 一层是进度图,用于展示进度条对应的视频缩略图。根据用户鼠

    2024年02月10日
    浏览(48)
  • 20230626----重返学习-Vue的学习路线-常用的vue指令-v-model-vue常见面试题

    如何学习Vue? 第一条线:视图线 template 或 jsx语法 指令「内置的14个指令和自定义指令」 jsx语法 VirtualDOM编译的机制 掌握DOM-diff算法 … 第二条线:数据线 学习 OptionsAPI / CompositionAPI 中的:语法、原理、区别等内容 OptionsAPI选项 学习 MVVM 的原理 数据是如何被监听的「Vue2和Vu

    2024年02月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包