ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

umi Max 布局与菜单:基于 ProLayout 的 layout 插件配置与实现原理

umi Max 布局与菜单:基于 ProLayout 的 layout 插件配置与实现原理 umi Max 布局与菜单基于 ProLayout 的 layout 插件配置与实现原理【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi本文围绕 umiumijs/max内置的layout插件展开讲解如何在构建时配置与运行时配置中开启并定制 Ant Design 的 ProLayout 布局与侧边栏菜单包括title、locale、logo、logout、rightRender等常用属性以及路由级扩展配置name、icon、access、flatMenu、xxxRender、hideInXXX的使用方法并结合仓库中的插件源码 packages/plugins/src/layout.ts 与示例工程 examples/max深入剖析菜单自动生成、图标按需加载与 403/404 兜底的底层实现机制。布局插件介绍为了降低研发成本umi 将布局通过 Umi 插件的方式内置只需简单的配置即可拥有 Ant Design 的 LayoutProLayout包括导航以及侧边栏用户无需关心布局本身。其核心能力包括默认为 Ant Design 的 Layoutant-design/pro-layout/ant-design/pro-components支持它全部配置项顶部导航/侧边栏菜单根据路由中的配置自动生成默认支持对路由的 403/404 处理和 Error Boundary搭配access插件一起使用可以完成对路由权限的控制搭配initial-state插件和 数据流 插件一起使用可以拥有默认用户登录信息的展示。从源码结构看插件通过api.describe声明key: layout且enableBy为api.EnableBy.config见 packages/plugins/src/layout.ts#L54-L63意味着只要在配置文件中出现layout属性插件即被启用这也是“配置开启”这一启用方式的实现来源。构建时配置可以通过配置文件config/config.ts或.umirc.ts中的layout属性开启插件。import { defineConfig } from umi; export default defineConfig({ layout: { title: Ant Design, locale: false, // 默认开启如无需菜单国际化可关闭 }, });仓库示例工程 examples/max/.umirc.ts 中就使用了layout: { title: Ant Design Pro }这一最简写法。titleType:stringDefault: package.json 中的name显示在布局左上角的产品名默认值为包名。在插件生成的布局组件中可以看到这一默认逻辑title{userConfig.title || ${packageName}}其中packageName即取自api.pkg.name见 packages/plugins/src/layout.ts#L43 与生成Layout.tsx的模板 packages/plugins/src/layout.ts#L264。localeType:booleanDefault:false是否开启国际化配置。开启后路由里配置的菜单名会被当作菜单名国际化的 key插件会去 locales 文件中查找menu.[key]对应的文案默认值为该 key路由配置的name字段的值就是对应的 key 值。如果菜单是多级路由假设为二级路由菜单那么插件就会去 locales 文件中查找menu.[key].[key]对应的文案。该功能需要配置i18n使用如无需菜单国际化可配置false关闭。从源码看构建时locale配置最终会透传给 ProLayout 的menu属性menu{{ locale: userConfig.locale }}见 packages/plugins/src/layout.ts#L273同时当项目中启用locale插件时生成的布局还会引入useIntl并注入formatMessage见 packages/plugins/src/layout.ts#L237-L242。运行时配置运行时配置写在src/app.ts(x)中key 为layout。import { RunTimeLayoutConfig } from umijs/max; export const layout: RunTimeLayoutConfig (initialState) { return { // 常用属性 title: Ant Design, logo: https://img.alicdn.com/tfs/TB1YHEpwUT1gK0jSZFhXXaAtVXa-28-27.svg, // 默认布局调整 rightContentRender: () RightContent /, footerRender: () Footer /, menuHeaderRender: undefined, // 其他属性参考 ProLayout 的完整文档 }; };除了下列插件支持的特有配置外运行时配置支持所有的构建时配置并透传给 ProLayout。在源码中运行时配置通过pluginManager.applyPlugins({ key: layout, type: modify, ... })收集后以{...runtimeConfig}的形式展开在ProLayout上因此优先级高于构建时配置见 packages/plugins/src/layout.ts#L243-L249 与 packages/plugins/src/layout.ts#L303。RunTimeLayoutConfig类型由插件在构建期生成到临时目录types.d.ts定义为OmitProLayoutProps, rightContentRender再叠加childrenRender、logout、rightContentRender、rightRender等扩展字段这为动态 layout 配置提供了完整的类型推导见 packages/plugins/src/layout.ts#L350-L391。titleType:stringDefault: package.json 中的name显示在布局左上角的产品名默认值为包名。logoType:stringDefault: Ant Design Logo显示在布局左上角产品名前的产品 Logo。若不提供插件会注入一个内置的 SVG Logo 组件Logo.tsx临时文件见 packages/plugins/src/layout.ts#L680-L775。logoutType:(initialState: any) voidDefault:null用于运行时配置默认 Layout 的 UI 中点击退出登录的处理逻辑默认不做处理。注默认在顶部右侧并不会显示退出按钮需要在app.ts(x)的运行时配置getInitialState中返回一个对象如包含name/avatar才可以显示头像与退出菜单。从源码看右侧头像区域的展示条件为initialState?.avatar || initialState?.name || runtimeConfig.logout点击退出菜单项时调用runtimeConfig.logout?.(initialState)见 packages/plugins/src/layout.ts#L513 与 packages/plugins/src/layout.ts#L561-L563。示例工程 examples/max/app.ts#L38-L42 中即演示了export const layout { logout() { alert(logout); }, };rightRenderType:(initialState: any) React.ReactNodeDefault: 展示用户名、头像、退出登录相关组件initialState是app.ts(x)中getInitialState返回的对象。生成的类型定义中该回调实际签名为(initialState, setInitialState, runtimeConfig) JSX.Element当项目配置了rightRender时它会完全接管右侧区域的渲染见 packages/plugins/src/layout.ts#L505-L511。ErrorBoundaryType:ReactNodeDefault: Ant Design Pro 的错误页发生错误后展示的组件。插件内部通过一个Exception组件包装路由出口Outlet它同时承担 404/403 兜底职责未匹配到路由时展示noFound/notFound自定义节点或默认的 404Result页匹配到的路由带unaccessible标记时展示unAccessible/noAccessible自定义节点或默认的 403Result页见 packages/plugins/src/layout.ts#L784-L811。扩展的路由配置Layout 插件会基于 Umi 的路由封装更多的配置项支持更多配置式的能力。新增侧边栏菜单配置布局路由级别展示/隐藏相关配置与权限插件结合配置式实现权限路由的功能。示例如下// config/route.ts export const routes [ { path: /welcome, component: IndexPage, name: 欢迎, // 菜单上显示的名称 icon: testicon, // 新页面打开 target: _blank, // 不展示顶栏 headerRender: false, // 不展示页脚 footerRender: false, // 不展示菜单 menuRender: false, // 不展示菜单顶栏 menuHeaderRender: false, // 权限配置需要与 plugin-access 插件配合使用 access: canRead, // 隐藏子菜单 hideChildrenInMenu: true, // 隐藏自己和子菜单 hideInMenu: true, // 在面包屑中隐藏 hideInBreadcrumb: true, // 子项往上提仍旧展示 flatMenu: true, }, ];示例工程 examples/max/.umirc.ts 给出了一个更贴近真实项目的路由写法混合使用了 antd 图标、icons 图标集与权限配置{ path: /users, icon: local:rice, // 本地 svg 图标icons 功能 component: users, name: users, wrappers: [/wrappers/foo, /wrappers/bar], }, { path: /accessAllow, icon: SmileFilled, // antd 图标实底风格 component: users, name: Allow, access: canReadFoo, // 权限标识 },nameType:string菜单上显示的名称没有则不展示该菜单。iconType:string菜单上显示的 antd 的 icon。为了按需加载layout 插件会帮你自动将其转化为 Antd icon 的 DOM。支持的类型可在 antd icon 组件文档中找到。示例// HomeOutlined / 线框风格 icon: home; // outlined 线框风格可简写 icon: HomeOutlined; // HomeFilled / 实底风格 icon: HomeFilled; // HomeTwoTone / 双色风格 icon: HomeTwoTone;兼容 icons 功能开启 icons 功能后可以使用图标集或本地图标具体请参考 icons 功能的配置与使用方法。从源码看图标按需加载的实现分为两步构建期插件读取ant-design/icons的类型声明收集全部图标名getAllIcons见 packages/plugins/src/layout.ts#L9-L27再对每个路由的icon做camelCase 首字母大写归一化命中homeOutlined/HomeOutlined形式后生成只引入所需图标的icons.tsx临时文件见 packages/plugins/src/layout.ts#L401-L430运行期再由生成的runtime.tsx中的patchRoutes把字符串图标替换为真实的 React 图标组件开启 icons 功能时优先走getIconComponent解析local:、图标集等带命名空间的写法见 packages/plugins/src/layout.ts#L459-L487。accessType:string当 Layout 插件配合access插件使用时生效。权限插件会将用户在这里配置的 access 字符串与当前用户所有权限做匹配如果找到相同的项且该权限的值为 false则当用户访问该路由时默认展示 403 页面。从源码看当项目启用access插件时生成的Layout.tsx会引入useAccessMarkedRoutes对菜单路由做标记给无权路由打上unaccessible随后由Exception组件识别并渲染 403 页面见 packages/plugins/src/layout.ts#L162-L167 与 packages/plugins/src/layout.ts#L256未启用access插件时该函数退化为恒等函数access字段不产生副作用。localeType:string菜单的国际化配置国际化的 key 是menu.${submenu-name}.${name}。flatMenuType:boolean默认为 false为 true 时在菜单中只隐藏此项子项往上提仍旧展示。打平菜单如果只想要子级的 menu 不展示自己的可以配置为 true。const before [{ name: 111 }, { name: 222, children: [{ name: 333 }] }]; // flatMenu true const after [{ name: 111 }, { name: 222 }, { name: 333 }];xxxRenderType:booleanxxxRender设置为 false即可不展示部分 layout 模块headerRenderfalse不显示顶栏footerRenderfalse不显示页脚menuRenderfalse不显示菜单menuHeaderRenderfalse不显示菜单的 title 和 logo。hideInXXXType:booleanhideInXXX可以管理 menu 的渲染hideChildrenInMenutrue隐藏子菜单hideInMenutrue隐藏自己和子菜单hideInBreadcrumbtrue在面包屑中隐藏。插件内部的 ProLayout 依赖解析与布局挂载以上配置最终都作用于ant-design/pro-components的ProLayout组件。从源码结构看插件在运行时按优先级alipay/tech-ui→ant-design/pro-components→ant-design/pro-layout寻找项目中已安装的布局组件包如果项目都没有自行依赖则回退到插件自带的ant-design/pro-components并通过modifyConfig写入 alias 保证版本一致见 packages/plugins/src/layout.ts#L65-L124。布局的挂载通过api.addLayouts实现以ant-design-pro-layout为 id 注册一个布局挂载条件为route.layout ! false也就是说任意路由只要显式配置layout: false即可退出 ProLayout 外壳见 packages/plugins/src/layout.ts#L818-L828。生成的Layout.tsx还会先过滤掉因 wrapper 导致的冗余路由层级再把清洗后的路由交给 ProLayout从而保证菜单 path 与真实路由一致见 packages/plugins/src/layout.ts#L252-L258。小结umiumijs/max的布局与菜单能力通过一个layout配置项即可开启构建时配置title/locale运行时在app.ts(x)中以RunTimeLayoutConfig定制logo、logout、rightRender等交互逻辑再配合路由上的name/icon/access/flatMenu/xxxRender/hideInXXX等扩展字段完成菜单与布局的精细化控制403/404 兜底、antd 图标按需加载、右侧用户区渲染均由插件生成的临时文件自动完成。完整配置示例可参考 examples/max/.umirc.ts 与 examples/max/app.ts插件完整实现见 packages/plugins/src/layout.ts配套文档包括 access、数据流 与 国际化。【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表