umi路由模块化设计:构建可扩展的前端应用

UMI是蚂蚁金服的底层前端框架,也是一个基于React的企业级前端应用框架,它提供了开箱即用的项目脚手架和插件化的配置,如路由构建、部署测试、文档工具、请求库等,帮助开发者快速搭建和管理复杂的前端项目,其设计目标是提高前端项目的开发效率和可维护性,尤其适用于大型复杂项目的开发与管理。

        路由不仅仅是页面之间导航的枢纽,它还负责管理应用的状态、控制用户体验的流畅性,以及支持深度链接和数据预取等关键功能。在React生态系统中,umi框架以其强大的路由管理能力脱颖而出,为开发者提供了一种灵活且高效的方式来构建现代单页应用,本文将揭示umi路由的精髓,并为项目中的路由设计提供深刻的启发和实用的指导。

目录

约定式路由

配置式路由

路由跳转传参

约定式路由

约定式路由就是不需要再去写路由表而是直接创建组件,umi底层会根据开发者创建的组件从而在内部生产路由表,比如我们在pages文件中创建如下几个tsx文件:

umi底层会自动给我们创建好路由表,从而不需要在手动去写路由表的内容:

这里我们可以做一个菜单导航进行一个路由的跳转,如下这里我们使用一个styled-components库进行一个样式操作,不了解styled-components推荐参考这篇文章:地址 ,我们在布局文件layout中进行如下操作:

import { NavLink, Outlet } from "umi";
import styled from "styled-components";

const StyleLayoutBox = styled.div`
  width: 100%;
  height: 20px;
  padding-bottom: 20px;
  border-bottom: 1px solid red;
  a {
    margin-right: 10px;
    color: #000;
    text-decoration: none;
    font-size: 20px;
    &.active {
      color: red;
    }
  }
  .container {
    margin: 20px auto;
  }
`
// 在 jsx 中使用
export default function App() {
  return (
    <StyleLayoutBox>
      <NavLink to="/">主页</NavLink>
      <NavLink to="/count">计数器</NavLink>
      <NavLink to="/user">个人中心</NavLink>
      <div className="container">
        <Outlet></Outlet>
      </div>
    </StyleLayoutBox>
  );
}

最终呈现的效果如下所示:

当然这里我们可以配置一下我们的二级路由,这里我们可以在一级路由的页面中设置一下二级路由的跳转路径,具体代码如下所示:

// 个人中心
import { NavLink, Outlet } from "umi";
import styled from "styled-components";

const StyleUserBox = styled.div`
  width: 100%;
  height: 30px;
  border-bottom: 1px solid #ccc;
  padding-bottom: 10px;
  a {
    margin-right: 20px;
    &.active {
    color: #007bff;
    }
  }
  .container {
    margin-top: 20px;  
  }
`

const PersonalPage = () => {
  return (
    <StyleUserBox>
      <NavLink to="/user/order">订单管理</NavLink>
      <NavLink to="/user/profile">个人中心</NavLink>
      <div className="container">
        <Outlet></Outlet>
      </div>
    </StyleUserBox>
  )
};

export default PersonalPage;

页面呈现的效果如下所示:

可以看到从始至终,我们都没有创建任何的路由表,每一个组件默认都实现了懒加载,不需要开发者进行任何的配置,具体如下所示:

配置式路由

配置式路由需要在配置文件编写相应的路由表,在.umirc.ts文件或者config文件夹下创建routes.ts都是可以的,这里我们就先在config/routes.ts文件中创建路由表即可:

const routes: any[] = [
    {
        path: '/',
        component: 'index',
        title: '首页'
    },
    {
        path: '/count',
        component: 'count',
        title: '计数器'
    },
    {
        path: '/user',
        component: 'user',
        title: '用户',
        routes: [
            // 重定向
            {
                path: '/user',
                redirect: '/user/order',
            },
            {
                path: '/user/order',
                component: 'user/order',
                title: '我的订单'
            },
            {
                path: '/user/profile',
                component: 'user/profile',
                title: '个人信息'
            }
        ]
    },
    {
        path: '*',
        component: '404',   
        title: '404'
    }
]

export default routes

然后我们在config.ts文件中配置一下全局的配置:

import { defineConfig } from "umi";
import routes from './config.routes'

export default defineConfig({
  // 配置式路由
  npmClient: 'pnpm',
  routes,
});

最终呈现的效果如下所示:

当然这里我们也可以使用全局的loading组件来实现网速缓慢时的loading加载效果,这里借助antd中的一个loading组件来实现:

import { Spin } from "antd";

export default () => {
  return <div>
    <Spin size="large"></Spin>
  </div>;
};

效果如下所示:

路由跳转传参

在UMI中的路由跳转是分为两类的,如下:

声明式导航:Link / NavLink;

编程式导航:history对象 / useNavigate => navigate()

history:这里我们需要借助umi中提供的history进行编程式路由导航,具体代码如下:

const OrderPage = () => {
    // 创建navigate对象
    const navigate = useNavigate();
    return (
        <div>
            <h1>我的订单</h1>
            <Button type="primary" onClick={()=> {
                // history.push('/user/profile');
                
                // 问号传参
                // history.push({
                //     pathname: '/user/profile',
                //     search: '?name=zhangsan&age=18'
                // })

                // 隐式传参, 在目标组件刷新后,参数不会丢失
                // history.push("/user/profile", {
                //     name: 'zhangsan',
                //     age: '18'
                // })
                
                // 需要在config.ts或者.unirc.ts中配置historyWithQuery选项之后,才能通过query进行传参
                history.push({
                    pathname: '/user/profile',
                    query: {
                        name: 'zhangsan',
                        age: '18'
                    }
                });
            }}>跳转到profile</Button>
        </div>
    );
};

这里我们需要在配置文件中配置如下属性才能够使用query进行传参:

navigate:这里我们可以借助umi中提供的 useNavigate 函数方法来进行编程式路由导航:

import { Button } from "antd";
import { useNavigate } from "umi";
const OrderPage = () => {
    // 创建navigate对象
    const navigate = useNavigate();
    return (
        <div>
            <h1>我的订单</h1>
            <Button type="primary" onClick={()=> {
                navigate({
                    pathname: "/user/profile",
                    search: "name=zhangsan&age=18",
                })
            }}>跳转到profile</Button>
        </div>
    );
};
  
export default OrderPage;

然后我们在跳转目标页面的组件中使用withRouter来实时获取到当前的传递过来的数据:

import { withRouter } from "umi";
const ProfilePage: React.FC<{ location: any }> = ({ location }) => {
    console.log(location.search);
    const usp = new URLSearchParams(location.search);
    console.log(usp.get("name"));
    console.log(usp.get("age"));
    
    return <div>个人信息</div>;
};
  
export default withRouter(ProfilePage);

最终呈现的效果如下所示:

在UMI的路由跳转中进行传参的方式分为三种,如下:

问号传参:?name=jack&age=18

这里我们就可以使用到编程式路由导航的方法进行问号传参的方式:

路径传参:/profile/jack/18

在路径传参中,我们给路由表配置了如下动态路由形成了路径传参:

设置完成之后,我们正常访问路径的话是访问不到的,需要加上我们设置的动态路由才可以:

那么我们如何获取传递的参数呢?这里我们可以通过umi提供的hook函数来获取当前的路径传参

import { useParams } from "umi";

const CountPage = () => { 
  const params = useParams();
  console.log(params);
  return <div>计算中心</div>;
};

export default CountPage;

最终呈现的效果如下所示:

当然我们也可以使用umi中的withRouter来对组件进行包裹,这样打印props的话就会获取到许多我们有用的属性,如:history、location、match、navigate、params等等,代码如下所示:

import { withRouter } from "umi";

const CountPage = (props: any) => { 
  console.log(props);
  return <div>计算中心</div>;
};

export default withRouter(CountPage);

最终在控制台打印的数据,我们可以在match属性中找到我们想要的数据:

隐式传参:state:{name:"ja"}

隐式传参的方式如下所示:

import { Button } from "antd";
import { useNavigate } from "umi";
const OrderPage = () => {
    // 创建navigate对象
    const navigate = useNavigate();
    return (
        <div>
            <h1>我的订单</h1>
            <Button type="primary" onClick={()=> {
                // 隐式传参
                navigate("/user/profile", {
                    state: {
                        name: "zhangsan",
                        age: 18
                    },
                })
            }}>跳转到profile</Button>
        </div>
    );
};
export default OrderPage;

然后目标组件的话通过 location.state 拿到隐式传参的数据:

当然也是可以采用下面的方式进行隐式传参数据的获取:

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-18 19:06:01       50 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-18 19:06:01       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-18 19:06:01       43 阅读
  4. Python语言-面向对象

    2024-07-18 19:06:01       54 阅读

热门阅读

  1. 探索HiFi智能编解码器的奇妙世界

    2024-07-18 19:06:01       15 阅读
  2. 大话设计模式

    2024-07-18 19:06:01       14 阅读
  3. QT老版本下载指南

    2024-07-18 19:06:01       18 阅读
  4. react native 截图并保存到相册

    2024-07-18 19:06:01       18 阅读
  5. MySQL入门学习-深入索引.函数和表达式索引

    2024-07-18 19:06:01       20 阅读
  6. 超撒加密2.0

    2024-07-18 19:06:01       23 阅读
  7. P1009 [NOIP1998 普及组] 阶乘之和

    2024-07-18 19:06:01       18 阅读
  8. Springboot加载机制

    2024-07-18 19:06:01       15 阅读