Pro V5 是可以渐进使用的,只要升级到 umi@3 即可使用这些特性,新的数据流虽然简单高效但是并不能满足所有的场景,我们可以混合适应,慢慢迁移。当然我们希望可以尽早迁移来减少历史债务。
initialState
在 v5 中替代了原来的自带 model,global
,login
,setting
都并入了 initialState 中。我们需要删除 src/models/global.ts
,src/models/login.ts
,src/models/setting.ts
,并且将请求用户信息和登陆拦截放到 src/app.tsx
中。
我们可以将 initialState
理解为一个默认的 model,里面可以将项目中需要的不频繁修改的数据注入。
import { history } from 'umi';import { Settings as ProSettings } from '@ant-design/pro-layout';import { queryCurrent } from '@/services/user';import defaultSettings from '../config/defaultSettings';export async function getInitialState(): Promise<{currentUser?: API.CurrentUser;settings?: ProSettings;}> {// 如果是登录页面,不执行if (history.location.pathname !== '/user/login') {try {const currentUser = await queryCurrent();return {currentUser,settings: defaultSettings,};} catch (error) {history.push('/user/login');}}return {settings: defaultSettings,};}
在新的架构中 Layout 被作为插件使用,作为了替代品我们在 app.ts
中提供了 layout
的配置项来支持运行时配置,我们需要将 footer 和 menu 的自定义迁移到 app.ts
中,在 return 中我们可以原来的任何 props 配置。
import React from 'react';import { history } from 'umi';import { BasicLayoutProps, Settings as ProSettings } from '@ant-design/pro-layout';import RightContent from '@/components/RightContent';import Footer from '@/components/Footer';export const layout = ({initialState,}: {initialState: { settings?: ProSettings };}): BasicLayoutProps => {return {rightContentRender: () => <RightContent />,disableContentMargin: false,footerRender: () => <Footer />,menuHeaderRender: false,...initialState?.settings,};};
在 V4 中我们将 layout 的配置放到了 model 中,在 V5 中我们将其放入了 initialState
中,还有非常重要的用户信息也在 initialState
进行了初始化。 默认配置中的 layout
属性变为 'side' | 'top' | 'mix'
,这里需要注意一下,默认是 mix
。
export async function getInitialState(): Promise<{currentUser?: API.CurrentUser;settings?: ProSettings;}> {// 如果是登录页面,不执行if (history.location.pathname !== '/user/login') {try {const currentUser = await queryCurrent();return {currentUser,settings: defaultSettings,};} catch (error) {history.push('/user/login');}}return {settings: defaultSettings,};}
这里是 Footer 的配置可以修改为自己需要的。
import React from 'react';import { GithubOutlined } from '@ant-design/icons';import { DefaultFooter } from '@ant-design/pro-layout';export default () => (<DefaultFootercopyright="2019 蚂蚁金服体验技术部出品"links={[{key: 'Ant Design Pro',title: 'Ant Design Pro',href: 'https://pro.ant.design',blankTarget: true,},{key: 'github',title: <GithubOutlined />,href: 'https://github.com/ant-design/ant-design-pro',blankTarget: true,},{key: 'Ant Design',title: 'Ant Design',href: 'https://ant.design',blankTarget: true,},]}/>);
我们的权限改造也依赖了它,对于原来的权限我们可以完全将其删除, 并且在 src/access.ts
增加相应的权限标识,以 pro 为例,我们只使用了 canAdmin
。
// src/access.tsexport default function (initialState: { currentUser?: API.CurrentUser | undefined }) {const { currentUser } = initialState || {};return {canAdmin: currentUser && currentUser.access === 'admin',};}
迁移之后我们就可以将原来的权限组件删除。 src/utils/Authorized.ts
,src/utils/authority.ts
,src/components/Authorized/**
。
在 config.ts 的 router 中我们需要删除 authority
,修改为 access: 'canAdmin'
同时我们可以 util 中的所有关于权限的方法。
对于运行时的代码,我们提供了两个 API 来帮助我们自定义任何形态的 UI 和逻辑,这里有个一看就懂的 demo。
import React from 'react';import { useAccess, Access } from 'umi';const PageA = (props) => {const { foo } = props;const access = useAccess(); // access 的成员: canAdminif (access.canReadFoo) {// 如果可以读取 Foo,则...}return (<div><Access accessible={access.canAdmin} fallback={<div>Can not read foo content.</div>}>Foo content.</Access><Access accessible={access.canDeleteFoo(foo)} fallback={<div>Can not delete foo.</div>}>Delete foo.</Access></div>);};
原有的项目中 request 定义在 src/utils/request.ts
中,在 V5 中需要用 umi 中 import ,各项配置需要写在 app.ts 中进行实现。
import { RequestConfig } from 'umi';export const request: RequestConfig = {timeout: 1000,errorConfig: {},middlewares: [],requestInterceptors: [],responseInterceptors: [],errorHandler,};
V5 中还自带了 useRequest hooks ,很多页面并不需要数据共享,我们可以用 useRequest 来快速的网络请求,并且内置了 loading 和 run 来指示状态和重新请求数据,使用方式极为简单。
import { useRequest } from 'umi';export default () => {const { data, error, loading } = useRequest(() => {return services.getUserList('/api/test');});if (loading) {return <div>loading...</div>;}if (error) {return <div>{error.message}</div>;}return <div>{data.name}</div>;};
由于将所有的逻辑做了拆离,很多依赖都不在需要了,我们可以将其中一些依赖进行删除来增加依赖的安装速度。
path-to-regexpreact-helmet-asyncjsdom-globalenzymechalkcheckFiles
现在 layout 作为插件会一直包裹在最外层,如果我们想在某个路由中不使用 layout,可以在菜单中配置 layout=false 来隐藏。详细的配置可以看这里。
对于 SettingDrawer,为了方便集成和部署,我们开发了 umi-plugin-setting-drawer
,只要在项目中安装这个插件即可快速使用。