umi4js集成Material UI

2023-11-17

效果图

在这里插入图片描述

创建umi项目

一直在用ant design pro做项目,着实有点儿审美疲劳了,正好最近有个小项目尝试下Material UI,发现Material UI也挺好用的,在此做个总结。

创建umi项目

# 官方推荐使用pnpm构建项目

pnpm dlx create-umi@latest

umi 目录结构

.
├── config
│   └── config.ts
├── dist
├── mock
│   └── app.ts|tsx
├── src
│   ├── .umi
│   ├── .umi-production
│   ├── layouts
│   │   ├── BasicLayout.tsx
│   │   ├── index.less
│   ├── models
│   │   ├── global.ts
│   │   └── index.ts
│   ├── pages
│   │   ├── index.less
│   │   └── index.tsx
│   ├── utils // 推荐目录
│   │   └── index.ts
│   ├── services // 推荐目录
│   │   └── api.ts
│   ├── app.(ts|tsx)
│   ├── global.ts
│   ├── global.(css|less|sass|scss)
│   ├── overrides.(css|less|sass|scss)
│   ├── favicon.(ico|gif|png|jpg|jpeg|svg|avif|webp)
│   └── loading.(tsx|jsx)
├── node_modules
│   └── .cache
│       ├── bundler-webpack
│       ├── mfsu
│       └── mfsu-deps
├── .env
├── plugin.ts 
├── .umirc.ts // 与 config/config 文件 2 选一
├── package.json
├── tsconfig.json
└── typings.d.ts

启用插件

# 安装插件
pnpm add -D @umijs/plugins
// config/config.ts
export default defineConfig({
  //...
  plugins: [
    "@umijs/plugins/dist/tailwindcss.js",
    "@umijs/plugins/dist/dva",
    '@umijs/plugins/dist/initial-state',
    '@umijs/plugins/dist/model',
  ],
  // mock: false,
  tailwindcss: {},
  dva: {},
  initialState: {},
  model: {},
});

dva

// src/model/layout.ts
export interface LayoutModelState {
  opened: boolean;
  isOpen: Array<string>;
}

export default {
  namespace: 'layout',
  state: {
    opened: true,
    isOpen: [],
  },
  reducers: {
    openLeftDrawer(state: LayoutModelState) {
      return {
        ...state,
        opened: state.opened,
      };
    },
    openMenu(state: { isOpen: Array<string> }, { payload }: { payload: any }) {
      const { menuId } = payload;
      return {
        ...state,
        isOpen: [ menuId ]
      };
    },
  },
};

页面中使用dva

const mapStateToProps = (state: any) => {
  return {
    layout: state.layout,
    loading: state.loading,
  };
};

const Layout: React.FC = (props: any) => {
  // 省略代码
  return (
    <>
      <Main theme={themes} open={props.layout.opened}>
    </>
  )

};
export default connect(mapStateToProps)(Layout);

使用useDispatch, useSelector

const Layout: React.FC = (props: any) => {
  const dispatch = useDispatch();
  const layoutModel: LayoutModelState = useSelector((state: any) => {
   return state.layout;
 });
  // 省略代码
  return (
    <>
      <Main theme={themes} open={layoutModel.opened}>
    </>
  )
};
export default Layout;

编辑layout

...

<ColorModeContext.Provider value={colorMode}>
      <StyledEngineProvider injectFirst>
        <ThemeProvider theme={themes}>
          <CssBaseline />
          <Box sx={{ display: 'flex' }}>
            {/* header */}
            <AppBar
              enableColorOnDark
              position="fixed"
              color="inherit"
              elevation={0}
            >
              <Toolbar>
                <Header />
              </Toolbar>
            </AppBar>
            {/* drawer */}
            <Sidebar />
            {/* main content */}
            <Main theme={themes} open={props.layout.opened}>
              {/* breadcrumb */}
              <Outlet />
            </Main>
            <Customization />
          </Box>
        </ThemeProvider>
      </StyledEngineProvider>
    </ColorModeContext.Provider>

ColorModeContext: 用于切换light/dark模式。

createTheme

const themes = React.useMemo(
    () =>
      createTheme({
        palette: {
          mode,
          ...(mode === 'light'
            ? {
                primary: {
                  light: colors.primaryLight,
                  main: colors.primaryMain,
                  200: colors.primary200,
                },
                secondary: {
                  light: colors.secondaryLight,
                  main: colors.secondaryMain,
                },
              }
            : {
                primary: {
                  light: colors.darkPrimaryLight,
                  main: colors.darkPrimaryMain,
                  200: colors.darkPrimary200,
                },
                secondary: {
                  light: colors.darkSecondaryLight,
                  main: colors.darkPrimaryMain,
                },
              }),
        },
      }),
    [mode],
  );

改变mode实现light/dark的切换

根据routes展示菜单

// routes
[
  {
    id: '1',
    icon: 'dashboard',
    title: 'Dashboard',
    type: 'group',
    caption: 'Dashboard Caption',
    routes: [
      {
        id: '2',
        path: '/dashboard',
        icon: 'dashboard',
        type: 'collapse',
        title: 'Dashboard',
        routes: [
          {
            id: '3',
            path: '/dashboard/one',
            type: 'item',
            title: '测试菜单',
            component: 'index'
          },
          {
            id: '4',
            path: '/dashboard/two',
            type: 'item',
            title: '测试菜单2',
            component: 'docs'
          }
        ]
      },
      {
        id: '5',
        path: '/dashboard/two',
        type: 'item',
        title: '测试菜单2',
        component: 'docs'
      }
    ],
  },
]

type=“group”: 菜单分组。
type=“collapse”: 菜单目录。
type=“item”: 菜单。

服务端返回routes

// app.tsx

let extraRoutes: any[];

export function patchClientRoutes({ routes }: {routes: any}) {
  routes[0].children = [];
  forEachRouter(routes[0], extraRoutes);
}

function forEachRouter(currentRoute: any, routes: any) {
  routes.forEach((route: any) => {
    if(!!route.routes && route.routes.length > 0) {
      forEachRouter(currentRoute, route.routes);
    }
    if(route.type === 'item') {
      const tempComponent = Loadable(lazy(() => import(`@/pages/${route.component}`)));
      currentRoute.children.unshift({
        path: route.path,
        element: createElement(tempComponent)
      });
    }
  });
}

export async function render(oldRender: () => void) {
    const res = await fetch("/api/sys/get/routes");
    const data = await res.json()
    extraRoutes = data.data;
    oldRender();
}

patchClientRoutes: 该函数直接修改routes,实现组件动态注册。
Loadable: 进度条,类似于nprogress.js。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

umi4js集成Material UI 的相关文章

  • 如何在 Angular 6 中过滤复杂结构化的 Json 数据

    我有一个复杂的结构化 json 数据 需要在我的 Angular 6 应用程序中应用高级过滤 JSON 数据 StudentId 1 StudentName Student1 Sex M Programs StudentId 1 Progr
  • 将键和值转换为具有单个键/值的对象的类型安全方法

    我想写一个函数valueToObject给定一个键和一个值 会生成一个具有该单个键和值的对象 例如 valueToObject myKey 3 should return myKey 3 我尝试了以下代码 type Wrapped
  • 打字稿地图迭代失败

    我正在使用下面的函数来比较两个地图 有趣的是 for 循环内的代码永远不会被执行 所以 console log key val 代码永远不会被执行 当然 我确保我正在比较的映射不为空并且大小相同 以强制执行 for 循环内的代码 我犯了一个
  • 如何在 Angular 4 材料的 Stepper 中提交表单

    如何在角材料的步进器中提交表单数据 我正在遵循角材料的示例https material angular io components stepper examples https material angular io components
  • ionic 2 从 json 填充选择选项

    我正在尝试动态填充ion select带有 json 对象的下拉列表 我的 html 组件如下所示
  • 如何访问打字稿中的组件

    我有一个基本的 Angular 应用程序 如下所示 app component html h1 Test Umgebung h1 div div
  • TypeScript 中的可等待类型

    我在 JavaScript 中经常使用 async await 现在我正在逐渐将代码库的某些部分转换为 TypeScript 在某些情况下 我的函数接受将被调用和等待的函数 这意味着它可以返回一个承诺 只是一个同步值 我已经定义了Await
  • 从条件映射类型中排除“{}”

    我们在以下界面上工作 interface A a string b string c number d number 我们有一个类型可以让每个键都在T optional如果他们的类型是string and required如果是number
  • 节点需要导入语句的文件扩展名

    我一直在构建一个打字稿应用程序 其中我从文件中导入了一些常量 VS Code 的自动导入为我完成了这项工作 但是当我编译并运行该文件时 它抛出了一个错误 因为它找不到该模块 似乎错误来自于导入语句没有文件扩展名 但它只出现在编译的 java
  • 来自函数参数的动态 Typescript 对象属性

    我有一个函数 它接受一个n参数的数量 并生成一个新对象 其中包含参数到唯一哈希的键值映射 Typescript 有没有办法从函数的参数动态推断返回对象的键 Example 生成字典的CreateActionType函数 function c
  • NestJs:如何使 Body 输入形状与实体的 DTO 不同?

    我的照片和标签对象有 DTO 如下所示 export class PhotoDto readonly title string readonly file string readonly tags TagDto export class T
  • TSLint :变量名必须是驼峰或大写

    我有一些以下划线开头的变量名称 更新 tslint json 后我仍然收到此警告 tslint json extends tslint recommended rules variable name true ban keywords ch
  • 我们必须在打字稿中使用“this”关键字吗?

    我正在写一个小例子来验证Name Email Password and ConfirmPassword通过打字稿 我试过了 interface IValidation CheckingNameAndEmail boolean Checkin
  • 使用 Typings 安装 React 相关类型定义时出现问题

    每当我尝试安装任何与 React 相关的包类型定义时 例如react boostrap fixed data table or react router尝试构建时出现以下类型的错误tsc Typings globals react boot
  • 防止被 0 除的 Typescript 类型

    我正在使用打字稿创建一个用于培训目的的计算系统 但在除法过程中出现打字错误 您知道如何解决吗 type Variable value number resolve gt number type NoZeroVariable value Om
  • Typescript 1.8 模块:从文件夹导入所有文件

    我正在使用 Typescript 构建一个大型库 其中包含 100 个独立的 ts 文件 以前我用过导出模块XXX 重命名为导出命名空间 XXX稍后 对于我的所有课程 但正如书籍所说 这不是推荐的方法 我应该使用 import 代替 所以我
  • 如何使用 Typescript 从 mui 扩展调色板

    我正在尝试扩展 mui 提供的调色板 覆盖主色 次要颜色等效果很好 但如果我想在之后创建一组自定义颜色 我不知道如何使其工作 有很多没有打字稿的例子 但是当这个人进入游戏时 事情就变得更加棘手 假设我有这个 主题 tsx palette p
  • 将隐式键和值类型关系传递给 TypeScript 泛型

    Target 注意替换isInvalid false and validationPending false按辅助类 函数 const controlsAccess senderName ControlAccess
  • React-Native 博览会 POST Blob

    我正在使用 React Native 和 expo 并尝试通过 fetch api 发布 blob 图像 我对正文使用表单数据格式 并且我有下一个代码 const blob await response blob const form ne
  • 类型“Promise”上不存在属性“finally”

    我试图对承诺使用finally 方法 但我不断收到此错误 Property finally does not exist on type Promise

随机推荐

  • Maven引入本地Jar包

    项目场景 有些jar包在Maven Central Repository 中没有 需要引入本地jar包 问题描述 使用本地的jar要解决两个问题 第一 引入项目中编译通过 本地开发正常启动 第二 项目打包正常 步骤 1 新建一个与src同级
  • 如何在配置文件中注释掉和取消注释行

    You may have seen instructions that tell you to uncomment or comment out lines in a configuration or source code file Th
  • vue动态绑定class和style,三目运算符条件判定

    动态绑定class和style 给绑定的class style传递一个对象 以动态切换 div div 给绑定的class传递一个数组 以应有一个class列表 三元运算 div div 数组对象 div div 给绑定的st
  • 电信光纤猫虚拟服务器设置方法,电信光纤猫怎么设置宽带拨号?

    网络运营商在装光纤宽带的时候会赠送一个光纤猫 里面的配置是工作人员预设好的 而这个光猫也带有自动拨号的功能 所以电信的光纤猫是不需要拨号的 但我们如果需要使用拨号连接宽带 该怎么设置呢 阅读下文了解电信光纤猫设置宽带拨号上网的方法 操作之前
  • 利用OpenCV的Grabcut()函数实现图像的前景与背景的分割-并对Grabcut()作详细介绍

    图像处理开发需求 图像处理接私活挣零花钱 请加微信 QQ 2487872782 图像处理开发资料 图像处理技术交流请加QQ群 群号 271891601 Graphcut是一种基于图论的分割方法 在计算机视觉领域中应用于前景分割 医学处理 纹
  • C++第二章课后习题

    如果可以 还请点个赞 2 1 C 语言有哪些主要特点和有点 解 1全面兼容c 2面向对象的方法 2 2 下列标识符有哪些是合法的 Program page lock test2 3inl mail A B C D 解 第1 3 4 7个 2
  • 用telnet来观察http协议的通信过程

    用windows下的telnet命令来观察http协议的通信过程如下 1 开始 R 在弹出对话框里输入cmd 2 以下是cmd窗口的输入输出 用户输入文本内容为红色 按键为黄色 部分内容在运行过程中可能会被清除 所以可能看到的内容跟下面不一
  • 3dmax渲染完就卡住不动怎么办?

    有很多种原因都可能会导致3DMAX卡死 需要一个个排查 一 3dmax和系统语言不兼容 解决方法是把电脑里语言设置的兼容性打开 二 3dmax内存分配不足 把动态内存限制设置到1W以上或是直接设置为0 不限制 三 渲染设置错误 可以尝试重置
  • win10利用annaconda安装tensorflow1.8.0

    之前在ubuntu安装tensorflow走过很多弯路 也重装过很多次系统 今天在windows下安装时特意请求大神支援 一次性通过 现分享经验如下 以下安装包链接 链接 https pan baidu com s 1z3fr8kH3azt
  • 如何在github上搭建自己的博客

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 之前闲暇之余尝试着在github上搭建自己的博客 搭建过程中发现没有自己想象的那么容易 几经波折 好不容易才搭建好了雏形 现在就将在github上构建自己博客的整个流程好好
  • 写一篇预制构件厂员工管理方案

    预制构件厂员工管理方案一 招聘1 招聘程序应严格按照法定程序进行 包括发布招聘公告 收集报名材料 审核 录用等 2 根据企业对员工的要求 组织专业的面试 以确定最合适的候选人 二 培训1 为新员工组织培训 介绍公司的各项政策 工作要求和工作
  • Hadoop完全分布式集群——Hadoop 配置

    前面已完成VMware虚拟机安装与配置 参考前一篇Hadoop完全分布式集群 VMware虚拟机安装与配置 夏雨和阳阳的博客 CSDN博客 下面将进行Hadoop 配置 一 slave1 slave2节点配置修改 slave1 slave2
  • 推荐 OS X 下最方便实用的六款解压缩软件

    对于我们这种资料特别多 随时都需要跟工作伙伴沟通传递资料的人来说 一款方便的压缩软件真的太重要了 不仅可以节省时间 节省内存 更重要的是提高工作效率 今天废鱼就给大家推荐几款常用压缩软件 The Unarchiver The Unarchi
  • 【华为OD统一考试B卷

    在线OJ 本题通过率100 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1
  • 2021全国大学生电子设计竞赛F题(智能送药小车)国一赛后总结

    作为2022年的第一篇博客 思索了很久 就以此为题吧 11月7号随着电赛比赛的结束 我的大学竞赛生涯也差不多告一段落了 那天的心情也是无法用语言形容 第二天就又回归了正常的上课生活 2021年的电赛 既让人期盼 又存在许多变数 这一切都要从
  • java日期格式化yyyy-mm-dd

    在 Java 中 你可以使用 SimpleDateFormat 类来格式化日期 以 yyyy MM dd 为例 你可以这样写 SimpleDateFormat dateFormat new SimpleDateFormat yyyy MM
  • 回调函数 —— 借助中间通用函数(形参里有函数指针,实现函数注册)调用不同的回调函数 (多态/分层)

    回调函数传参 函数指针做函数参数 回调函数 目录 背景 回调函数是实现函数分层且单向依赖的好办法 使用函数指针运行 struct结构体回调函数代码更清晰 简单理解回调函数 Demo 其他回调函数博文 背景 这是我在实际工作中遇到的问题 线程
  • VSCode中简单使用Git

    在一个目录下clone项目 git clone 项目 git 使用VScode 打开项目 使用vscode修改代码并提交代码 修改代码 点击 相当于git add 点击对号 等于git commit m 备注信息 右边的箭头输入需要备注的信
  • Angular6学习笔记5:修改组件的属性并实时显示(ngModel)

    修改组件的属性并实时显示 ngModel 继学习笔记4以后 可以在一个AppComponent中显示了heroesComponent的属性信息 但是hero的Name往往是可以更改的 并将更改后的数据进行实时显示 1 将hero的Name重
  • umi4js集成Material UI

    umi4js集成Material UI 效果图 创建umi项目 创建umi项目 umi 目录结构 启用插件 dva 页面中使用dva 使用useDispatch useSelector 编辑layout createTheme 根据rout