欢迎页
未登录访问项目,初始页会直接跳转到 欢迎 页. 从路由配置可以看到,如果我们访问 http://localhost:8000/
, 能匹配到的路由只有被 redirect 到 Welcome 组建.
框架布局与核心组件
路由分别经过了 SecurityLayout ,BasicLayout 组件,以及顶部的BlankLayout 组件. 那么这三个组件是什么作用呢?
BlankLayout组件
组件位置: src/layouts/BlankLayout
, 该组件是项目的顶级组件, 可以在开发模式下更好的显示错误提示. 当前组件可以理解为一个空白组件.
import React from 'react';
import { Inspector } from 'react-dev-inspector';
const InspectorWrapper = process.env.NODE_ENV === 'development' ? Inspector : React.Fragment;
const Layout: React.FC = ({ children }) => {
// {children} 是dom内容,可以理解为 vue中的插槽
// dom的内容会直接被解析到这里
// InspectorWrapper 是根据是否为开发模式而替换为 Inspector 或正常的React虚拟组件
// Inspector 可以使我们在开发阶段 代码报错 提示的更友好
return <InspectorWrapper>{children}</InspectorWrapper>;
};
export default Layout;
SecurityLayout 组件
组件位置: src/layouts/SecurityLayout
, 顾名思义,该组件应该是对安全访问方面做了一些控制.
这里实现了对是否登录的逻辑判断: 登录中,则显示 <PageLoading />
组件; 如果未登录访问,则重定向至 /user/login
; 如果登录成功则返回子组件.
render() {
// 组件是否渲染完毕
const { isReady } = this.state;
// loading为获取user用户信息的网络请求状态 由dva-loading管控
const { children, loading, currentUser } = this.props;
// You can replace it to your authentication rule (such as check token exists)
// 你可以把它替换成你自己的登录认证规则(比如判断 token 是否存在)
const isLogin = currentUser && currentUser.userid;
const queryString = stringify({
redirect: window.location.href,
});
// 未登录 且在loading状态 或者组件未渲染完毕
if ((!isLogin && loading) || !isReady) {
return <PageLoading />;
}
// 未登录 且跳转未非登录页
if (!isLogin && window.location.pathname !== '/user/login') {
return <Redirect to={`/user/login?${queryString}`} />;
}
return children;
}
BasicLayout 组件
当前组件是后台页面布局的主要组件,使用了 ProLayout
进行实现.
ProLayout 是在 ant-design 基础之上封装的一个高级组件. ProLayout 可以提供一个标准又不失灵活的中后台标准布局,同时提供一键切换布局形态,自动生成菜单等功能。与 PageContainer 配合使用可以自动生成面包屑,页面标题,并且提供低成本方案接入页脚工具栏。
页面权限相关功能通过 Authorized
组件和route配置结合控制,大致思路是通过当前用户的 角色 , 和组件Authorized
属性 authority 所具有的权限做对比,从而控制组件内容是否渲染或者渲染为 noMatch
对应组件.这种实现思路和我们在 vue-element-admin 模板中的思路大致相同, 但和我们课程中的动态权限思路不同. 关于权限部分后期会针对性说明,暂时可以跨过.
/**
* Ant Design Pro v4 use `@ant-design/pro-layout` to handle Layout.
* @see You can view component api by: https://github.com/ant-design/ant-design-pro-layout
*/
...
return (
<ProLayout
logo={logo}
formatMessage={formatMessage}
{...props}
{...settings}
onCollapse={handleMenuCollapse}
onMenuHeaderClick={() => history.push('/')}
menuItemRender={(menuItemProps, defaultDom) => {
if (
menuItemProps.isUrl ||
!menuItemProps.path ||
location.pathname === menuItemProps.path
) {
return defaultDom;
}
return <Link to={menuItemProps.path}>{defaultDom}</Link>;
}}
breadcrumbRender={(routers = []) => [
{
path: '/',
breadcrumbName: formatMessage({ id: 'menu.home' }),
},
...routers,
]}
itemRender={(route, params, routes, paths) => {
const first = routes.indexOf(route) === 0;
return first ? (
<Link to={paths.join('/')}>{route.breadcrumbName}</Link>
) : (
<span>{route.breadcrumbName}</span>
);
}}
footerRender={() => {
if (settings.footerRender || settings.footerRender === undefined) {
return defaultFooterDom;
}
return null;
}}
menuDataRender={menuDataRender}
rightContentRender={() => <RightContent />}
postMenuData={(menuData) => {
menuDataRef.current = menuData || [];
return menuData || [];
}}
>
// 这里是权限控制 可以通过当前用户的角色 和authority 的角色列表做对比
// 当前项目不用考虑页面权限, 具体实现会在后续的教程里体现
<Authorized authority={authorized!.authority} noMatch={noMatch}>
{children}
</Authorized>
</ProLayout>
);
};
比如 config/route.ts 路由部分权限配置
...
routes: [
{
path: '/admin/sub-page',
name: 'sub-page',
icon: 'smile',
component: './Welcome',
authority: ['admin'],
},
],
UserLayout 组件
当前组件是包装了用户登录页的容器组件. 可以通过当前组件设置网页 title , meta , 国际化选择, 登录页logo , 页脚等功能.
return (
<HelmetProvider>
<Helmet>
<title>{title}</title>
<meta name="description" content={title} />
</Helmet>
<div className={styles.container}>
<div className={styles.lang}>
<SelectLang />
</div>
<div className={styles.content}>
<div className={styles.top}>
<div className={styles.header}>
<Link to="/">
<img alt="logo" className={styles.logo} src={logo} />
<span className={styles.title}>Ant Design</span>
</Link>
</div>
<div className={styles.desc}>
<FormattedMessage
id="pages.layouts.userLayout.title"
defaultMessage="Ant Design 是西湖区最具影响力的 Web 设计规范"
/>
</div>
</div>
// Login组件在这里渲染
{children}
</div>
<DefaultFooter />
</div>
</HelmetProvider>
);
登录页
我们可以直接访问 http://localhost:8000/user/login
来跳转登录页,或者在后台点击推出跳转登录页. 登录页对应组件 pages/User/login/index.tsx
登陆后sideBar多了一个 管理页 功能, 该页面是登陆后,而且用户 角色 是 admin 才会出现的. src/layouts/BasicLayout.tsx
权限控制的代码部分:
/** Use Authorized check all menu item */
const menuDataRender = (menuList: MenuDataItem[]): MenuDataItem[] =>
menuList.map((item) => {
const localItem = {
...item,
children: item.children ? menuDataRender(item.children) : undefined,
};
// 使用Authorized鉴权判断当前sideItem是否被渲染
return Authorized.check(item.authority, localItem, null) as MenuDataItem;
});
总结
我们基本上已经搞清楚了 ant design pro 后台框架模板的基本结构,接下来我们需要按照自己的需求进行开发.
因为默认模板的登录页相对复杂,也不符合我们需求,我们可以自行替换需要的登录模板. 我们将在下一节开始具体开发.