015 在 Umi 中使用 Ant Design 编写全局布局

简介: 015 在 Umi 中使用 Ant Design 编写全局布局

image.png


前面14天的内容,我们几乎都在谈论 Umi 的相关概念,从这节课开始,我们就会真正进入实战阶段,如果需要给它取一个小标题,那我大概率会用《如何手写 Ant Design Pro》


这节课我们来实现页面级整体布局,所谓布局简单的理解就是网页的整体框框,也可以看成是,所有页面都共用的部分。 比如在 pc 上比较常见的上中下布局,在 app 上的底部 tabs 、全局浮动球等都属于布局需求。



约定的全局布局

约定式路由时的全局布局文件,实际上是在路由外面套了一层。比如,你的路由是:

约定 src/layouts/index.tsx 为全局路由,实际上是在路由外面套了一层返回一个 React 组件,并通过 useOutlet hook 或者 Outlet 组件渲染子组件。

比如以下目录结构,


.
└── src
    ├── layouts
    │   └── index.tsx
    └── pages
        ├── index.tsx
        └── users.tsx
复制代码


会生成路由,

[
  { exact: false, path: '/', component: '@/layouts/index',
    routes: [
      { exact: true, path: '/', component: '@/pages/index' },
      { exact: true, path: '/users', component: '@/pages/users' },
    ],
  },
]
复制代码


从组件角度可以简单的理解为如下关系:

<layout>
  <page>index</page>
  <page>users</page>
</layout>
复制代码


一个自定义的全局 layout 如下:

import React from "react";
import { useOutlet } from "umi";
const Layout = () => {
  const outlet = useOutlet();
  return (
    <div>
      Layout
      {outlet}
    </div>
  );
};
export default Layout;
复制代码



不同的全局 layout

你可能需要针对不同路由输出不同的全局 layout,Umi 不支持这样的配置,但你仍可以在 src/layouts/index.tsx 中对 location.path 做区分,渲染不同的 layout 。

比如想要针对 /login 输出简单布局,


import React from "react";
import { useOutlet } from "umi";
export default function(props) {
  const outlet = useOutlet();
  if (props.location.pathname === '/login') {
    return <SimpleLayout>{ outlet }</SimpleLayout>
  }
  return (
    <>
      <Header />
      { outlet }
      <Footer />
    </>
  );
}
复制代码



使用 Ant Design 实现基本布局

Ant Design 提供了好几种的布局方式,几乎中后台的所有布局都包括了。

image.png

详细的范例可以参考 Ant Design 官网,这里我们用最常见的 顶部导航 Header、侧边栏 Sider、内容区 Content、底部区域 Footer 的布局来做演示。


安装 Ant Design 和图标库

pnpm i antd @ant-design/icons
复制代码


使用 umi antd 插件

config/config.ts 配置中,修改 plugins 配置

import { defineConfig } from "umi";
export default defineConfig({
  // 最终值在插件中设置,所以这里不用写
  //   title: "Hello Umi",
  plugins: [
    require.resolve("@umijs/plugins/dist/model"),
+   require.resolve("@umijs/plugins/dist/antd"),
  ],
  model: {},
  antd: {},
});
复制代码


开启 antd 插件功能

config/config.ts 配置中,新增 antd 配置,这里是一次强调,添加完插件,要记得添加对应的配置。

Umi 中部分插件是默认开启,就无须配置。正常的插件都是配置开关。所有的插件都可以通过配置值为 false,来关闭它。

import { defineConfig } from "umi";
export default defineConfig({
  // 最终值在插件中设置,所以这里不用写
  //   title: "Hello Umi",
  plugins: [
    require.resolve("@umijs/plugins/dist/model"),
    require.resolve("@umijs/plugins/dist/antd"),
  ],
  model: {},
+ antd: {},
});
复制代码


新建 Layout 页面

新建页面文件 src/layouts/index.tsx,写出整体布局(用法来自 Ant Design 官网)

import { Layout } from "antd";
import React from "react";
const { Header, Content, Footer, Sider } = Layout;
const App: React.FC = () => {
  return (
    <Layout style={{ minHeight: "100vh" }}>
      <Sider></Sider>
      <Layout>
        <Header style={{ padding: 0 }} />
        <Content style={{ margin: "0 16px" }}></Content>
        <Footer style={{ textAlign: "center" }}></Footer>
      </Layout>
    </Layout>
  );
};
export default App;
复制代码


编写 Sider 和 Menu

import {
  DesktopOutlined,
  FileOutlined,
  PieChartOutlined,
  TeamOutlined,
  UserOutlined,
} from "@ant-design/icons";
import type { MenuProps } from "antd";
import { Breadcrumb, Layout, Menu } from "antd";
import React, { useState } from "react";
const { Header, Content, Footer, Sider } = Layout;
type MenuItem = Required<MenuProps>["items"][number];
function getItem(
  label: React.ReactNode,
  key: React.Key,
  icon?: React.ReactNode,
  children?: MenuItem[]
): MenuItem {
  return {
    key,
    icon,
    children,
    label,
  } as MenuItem;
}
const items: MenuItem[] = [
  getItem("Option 1", "1", <PieChartOutlined />),
  getItem("Option 2", "2", <DesktopOutlined />),
  getItem("User", "sub1", <UserOutlined />, [
    getItem("Tom", "3"),
    getItem("Bill", "4"),
    getItem("Alex", "5"),
  ]),
  getItem("Team", "sub2", <TeamOutlined />, [
    getItem("Team 1", "6"),
    getItem("Team 2", "8"),
  ]),
  getItem("Files", "9", <FileOutlined />),
];
const App: React.FC = () => {
  const [collapsed, setCollapsed] = useState(false);
  return (
    <Layout style={{ minHeight: "100vh" }}>
      <Sider
        collapsible
        collapsed={collapsed}
        onCollapse={(value) => setCollapsed(value)}
      >
        <div
          style={{
            height: "32px",
            margin: "16px",
            color: "#fff",
            textAlign: "center",
            fontSize: "16px",
          }}
        >
          Umi 4
        </div>
        <Menu
          theme="dark"
          defaultSelectedKeys={["1"]}
          mode="inline"
          items={items}
        />
      </Sider>
      {/* Layout 略 */}
    </Layout>
  );
};
export default App;
复制代码


编写 Footer

<Footer style={{ textAlign: "center" }}>
    Umi@4 实战小册 Created by xiaohuoni
</Footer>
复制代码


编写 Content 和面包屑

<Content style={{ margin: "0 16px" }}>
    <Breadcrumb style={{ margin: "16px 0" }}>
        <Breadcrumb.Item>User</Breadcrumb.Item>
        <Breadcrumb.Item>Bill</Breadcrumb.Item>
    </Breadcrumb>
    <div style={{ padding: 24, minHeight: 360 }}>Bill is a cat.</div>
</Content>
复制代码


渲染当前页面

前面提到过,我们使用 useOutlet hook 或者 Outlet 组件渲染子组件。将上面 Content 中的 Bill is a cat. 替换成 outlet 即可。

import { Outlet } from "umi";
// 其他内容略
<div style={{ padding: 24, minHeight: 360 }}>
    <Outlet />
</div>
复制代码


运行效果

执行 pnpm start 或者 npx umi dev,启动 umi 的开发服务,通过浏览器访问 http://127.0.0.1:8888/

image.png


源码归档

目录
相关文章
|
前端开发
ant design封装一个弹框组件
ant design封装一个弹框组件
107 0
|
6月前
Ant Design组件动态嵌套表单制作
Ant Design组件动态嵌套表单制作
219 0
|
前端开发 JavaScript 数据安全/隐私保护
react中ant.design框架配置动态路由
react中ant.design框架配置动态路由
210 0
|
资源调度 前端开发 JavaScript
ant-design-vue+vite主题切换详细步骤(简单案例)
ant-design-vue+vite主题切换详细步骤(简单案例)
867 0
|
前端开发 API
项目中Antd3与Antd4共存
本文适合使用Antd Design开发项目的小伙伴阅读。
项目中Antd3与Antd4共存
react-Ant Design框架中基础对话框和信息确认框的使用
在项目中,对话框和确认框是使用频率很高的组件,这里记录一下react-Ant Design框架中它们的基础用法
458 0
react-Ant Design框架中基础对话框和信息确认框的使用
|
缓存 移动开发
网友需求 - 使用 50 行代码在 Ant Design Pro 中完成 Umi 状态保持的多tabs布局
网友需求 - 使用 50 行代码在 Ant Design Pro 中完成 Umi 状态保持的多tabs布局
1975 1
网友需求 - 使用 50 行代码在 Ant Design Pro 中完成 Umi 状态保持的多tabs布局
|
前端开发
React工作66:ant design中Model宽度
React工作66:ant design中Model宽度
401 0
React工作66:ant design中Model宽度
|
前端开发 JavaScript 网络架构
Ant-design-vue项目实现动态路由
Ant-design-vue项目实现动态路由
379 0
Ant-design-vue项目实现动态路由
|
前端开发
ant-design-vue运行时动态切换主题色(1)
ant-design-vue运行时动态切换主题色(1)
486 0
ant-design-vue运行时动态切换主题色(1)