Commit 31af67c2 authored by WhatAKitty's avatar WhatAKitty Committed by 偏右

Fix dynamic component remount #114 #150 (#184)

parent debfa508
import dynamic from 'dva/dynamic'; import dynamic from 'dva/dynamic';
const data = [{ export const getNavData = app => [{
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/user'), import('../models/user'),
...@@ -18,7 +18,7 @@ const data = [{ ...@@ -18,7 +18,7 @@ const data = [{
children: [{ children: [{
name: '分析页', name: '分析页',
path: 'analysis', path: 'analysis',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/chart'), import('../models/chart'),
...@@ -28,7 +28,7 @@ const data = [{ ...@@ -28,7 +28,7 @@ const data = [{
}, { }, {
name: '监控页', name: '监控页',
path: 'monitor', path: 'monitor',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/monitor'), import('../models/monitor'),
...@@ -38,7 +38,7 @@ const data = [{ ...@@ -38,7 +38,7 @@ const data = [{
}, { }, {
name: '工作台', name: '工作台',
path: 'workplace', path: 'workplace',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/project'), import('../models/project'),
...@@ -55,7 +55,7 @@ const data = [{ ...@@ -55,7 +55,7 @@ const data = [{
children: [{ children: [{
name: '基础表单', name: '基础表单',
path: 'basic-form', path: 'basic-form',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/form'), import('../models/form'),
...@@ -65,7 +65,7 @@ const data = [{ ...@@ -65,7 +65,7 @@ const data = [{
}, { }, {
name: '分步表单', name: '分步表单',
path: 'step-form', path: 'step-form',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/form'), import('../models/form'),
...@@ -74,7 +74,7 @@ const data = [{ ...@@ -74,7 +74,7 @@ const data = [{
}), }),
children: [{ children: [{
path: 'confirm', path: 'confirm',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/form'), import('../models/form'),
...@@ -83,7 +83,7 @@ const data = [{ ...@@ -83,7 +83,7 @@ const data = [{
}), }),
}, { }, {
path: 'result', path: 'result',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/form'), import('../models/form'),
...@@ -94,7 +94,7 @@ const data = [{ ...@@ -94,7 +94,7 @@ const data = [{
}, { }, {
name: '高级表单', name: '高级表单',
path: 'advanced-form', path: 'advanced-form',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/form'), import('../models/form'),
...@@ -109,7 +109,7 @@ const data = [{ ...@@ -109,7 +109,7 @@ const data = [{
children: [{ children: [{
name: '查询表格', name: '查询表格',
path: 'table-list', path: 'table-list',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/rule'), import('../models/rule'),
...@@ -119,7 +119,7 @@ const data = [{ ...@@ -119,7 +119,7 @@ const data = [{
}, { }, {
name: '标准列表', name: '标准列表',
path: 'basic-list', path: 'basic-list',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/list'), import('../models/list'),
...@@ -129,7 +129,7 @@ const data = [{ ...@@ -129,7 +129,7 @@ const data = [{
}, { }, {
name: '卡片列表', name: '卡片列表',
path: 'card-list', path: 'card-list',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/list'), import('../models/list'),
...@@ -139,7 +139,7 @@ const data = [{ ...@@ -139,7 +139,7 @@ const data = [{
}, { }, {
name: '搜索列表(项目)', name: '搜索列表(项目)',
path: 'cover-card-list', path: 'cover-card-list',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/list'), import('../models/list'),
...@@ -149,7 +149,7 @@ const data = [{ ...@@ -149,7 +149,7 @@ const data = [{
}, { }, {
name: '搜索列表(应用)', name: '搜索列表(应用)',
path: 'filter-card-list', path: 'filter-card-list',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/list'), import('../models/list'),
...@@ -159,7 +159,7 @@ const data = [{ ...@@ -159,7 +159,7 @@ const data = [{
}, { }, {
name: '搜索列表(文章)', name: '搜索列表(文章)',
path: 'search', path: 'search',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/list'), import('../models/list'),
...@@ -174,7 +174,7 @@ const data = [{ ...@@ -174,7 +174,7 @@ const data = [{
children: [{ children: [{
name: '基础详情页', name: '基础详情页',
path: 'basic', path: 'basic',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/profile'), import('../models/profile'),
...@@ -184,7 +184,7 @@ const data = [{ ...@@ -184,7 +184,7 @@ const data = [{
}, { }, {
name: '高级详情页', name: '高级详情页',
path: 'advanced', path: 'advanced',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/profile'), import('../models/profile'),
...@@ -199,14 +199,14 @@ const data = [{ ...@@ -199,14 +199,14 @@ const data = [{
children: [{ children: [{
name: '成功', name: '成功',
path: 'success', path: 'success',
component: app => dynamic({ component: dynamic({
app, app,
component: () => import('../routes/Result/Success'), component: () => import('../routes/Result/Success'),
}), }),
}, { }, {
name: '失败', name: '失败',
path: 'fail', path: 'fail',
component: app => dynamic({ component: dynamic({
app, app,
component: () => import('../routes/Result/Error'), component: () => import('../routes/Result/Error'),
}), }),
...@@ -218,28 +218,28 @@ const data = [{ ...@@ -218,28 +218,28 @@ const data = [{
children: [{ children: [{
name: '403', name: '403',
path: '403', path: '403',
component: app => dynamic({ component: dynamic({
app, app,
component: () => import('../routes/Exception/403'), component: () => import('../routes/Exception/403'),
}), }),
}, { }, {
name: '404', name: '404',
path: '404', path: '404',
component: app => dynamic({ component: dynamic({
app, app,
component: () => import('../routes/Exception/404'), component: () => import('../routes/Exception/404'),
}), }),
}, { }, {
name: '500', name: '500',
path: '500', path: '500',
component: app => dynamic({ component: dynamic({
app, app,
component: () => import('../routes/Exception/500'), component: () => import('../routes/Exception/500'),
}), }),
}], }],
}], }],
}, { }, {
component: app => dynamic({ component: dynamic({
app, app,
component: () => import('../layouts/UserLayout'), component: () => import('../layouts/UserLayout'),
}), }),
...@@ -252,7 +252,7 @@ const data = [{ ...@@ -252,7 +252,7 @@ const data = [{
children: [{ children: [{
name: '登录', name: '登录',
path: 'login', path: 'login',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/login'), import('../models/login'),
...@@ -262,7 +262,7 @@ const data = [{ ...@@ -262,7 +262,7 @@ const data = [{
}, { }, {
name: '注册', name: '注册',
path: 'register', path: 'register',
component: app => dynamic({ component: dynamic({
app, app,
models: () => [ models: () => [
import('../models/register'), import('../models/register'),
...@@ -272,14 +272,14 @@ const data = [{ ...@@ -272,14 +272,14 @@ const data = [{
}, { }, {
name: '注册结果', name: '注册结果',
path: 'register-result', path: 'register-result',
component: app => dynamic({ component: dynamic({
app, app,
component: () => import('../routes/User/RegisterResult'), component: () => import('../routes/User/RegisterResult'),
}), }),
}], }],
}], }],
}, { }, {
component: app => dynamic({ component: dynamic({
app, app,
component: () => import('../layouts/BlankLayout'), component: () => import('../layouts/BlankLayout'),
}), }),
...@@ -291,9 +291,3 @@ const data = [{ ...@@ -291,9 +291,3 @@ const data = [{
icon: 'book', icon: 'book',
}, },
}]; }];
export function getNavData() {
return data;
}
export default data;
...@@ -11,8 +11,6 @@ import classNames from 'classnames'; ...@@ -11,8 +11,6 @@ import classNames from 'classnames';
import HeaderSearch from '../components/HeaderSearch'; import HeaderSearch from '../components/HeaderSearch';
import NoticeIcon from '../components/NoticeIcon'; import NoticeIcon from '../components/NoticeIcon';
import GlobalFooter from '../components/GlobalFooter'; import GlobalFooter from '../components/GlobalFooter';
import { getNavData } from '../common/nav';
import { getRouteData } from '../utils/utils';
import NotFound from '../routes/Exception/404'; import NotFound from '../routes/Exception/404';
import styles from './BasicLayout.less'; import styles from './BasicLayout.less';
...@@ -48,15 +46,15 @@ class BasicLayout extends React.PureComponent { ...@@ -48,15 +46,15 @@ class BasicLayout extends React.PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
// 把一级 Layout 的 children 作为菜单项 // 把一级 Layout 的 children 作为菜单项
this.menus = getNavData().reduce((arr, current) => arr.concat(current.children), []); this.menus = props.navData.reduce((arr, current) => arr.concat(current.children), []);
this.state = { this.state = {
openKeys: this.getDefaultCollapsedSubMenus(props), openKeys: this.getDefaultCollapsedSubMenus(props),
}; };
} }
getChildContext() { getChildContext() {
const { location } = this.props; const { location, navData, getRouteData } = this.props;
const routeData = getRouteData('BasicLayout'); const routeData = getRouteData('BasicLayout');
const firstMenuData = getNavData().reduce((arr, current) => arr.concat(current.children), []); const firstMenuData = navData.reduce((arr, current) => arr.concat(current.children), []);
const menuData = this.getMenuData(firstMenuData, ''); const menuData = this.getMenuData(firstMenuData, '');
const breadcrumbNameMap = {}; const breadcrumbNameMap = {};
...@@ -166,7 +164,7 @@ class BasicLayout extends React.PureComponent { ...@@ -166,7 +164,7 @@ class BasicLayout extends React.PureComponent {
}); });
} }
getPageTitle() { getPageTitle() {
const { location } = this.props; const { location, getRouteData } = this.props;
const { pathname } = location; const { pathname } = location;
let title = 'Ant Design Pro'; let title = 'Ant Design Pro';
getRouteData('BasicLayout').forEach((item) => { getRouteData('BasicLayout').forEach((item) => {
...@@ -203,15 +201,6 @@ class BasicLayout extends React.PureComponent { ...@@ -203,15 +201,6 @@ class BasicLayout extends React.PureComponent {
}); });
return groupBy(newNotices, 'type'); return groupBy(newNotices, 'type');
} }
getRouteComponent(item) {
if (this.routeComponents[item.path]) {
return this.routeComponents[item.path];
}
const component = item.component(this.props.app);
this.routeComponents[item.path] = component;
return component;
}
routeComponents = {};
handleOpenChange = (openKeys) => { handleOpenChange = (openKeys) => {
const lastOpenKey = openKeys[openKeys.length - 1]; const lastOpenKey = openKeys[openKeys.length - 1];
const isMainMenu = this.menus.some( const isMainMenu = this.menus.some(
...@@ -248,7 +237,7 @@ class BasicLayout extends React.PureComponent { ...@@ -248,7 +237,7 @@ class BasicLayout extends React.PureComponent {
} }
} }
render() { render() {
const { currentUser, collapsed, fetchingNotices } = this.props; const { currentUser, collapsed, fetchingNotices, getRouteData } = this.props;
const menu = ( const menu = (
<Menu className={styles.menu} selectedKeys={[]} onClick={this.onMenuClick}> <Menu className={styles.menu} selectedKeys={[]} onClick={this.onMenuClick}>
...@@ -361,7 +350,7 @@ class BasicLayout extends React.PureComponent { ...@@ -361,7 +350,7 @@ class BasicLayout extends React.PureComponent {
exact={item.exact} exact={item.exact}
key={item.path} key={item.path}
path={item.path} path={item.path}
component={this.getRouteComponent(item)} component={item.component}
/> />
) )
) )
......
...@@ -5,7 +5,6 @@ import DocumentTitle from 'react-document-title'; ...@@ -5,7 +5,6 @@ import DocumentTitle from 'react-document-title';
import { Icon } from 'antd'; import { Icon } from 'antd';
import GlobalFooter from '../components/GlobalFooter'; import GlobalFooter from '../components/GlobalFooter';
import styles from './UserLayout.less'; import styles from './UserLayout.less';
import { getRouteData } from '../utils/utils';
const links = [{ const links = [{
title: '帮助', title: '帮助',
...@@ -29,7 +28,7 @@ class UserLayout extends React.PureComponent { ...@@ -29,7 +28,7 @@ class UserLayout extends React.PureComponent {
return { location }; return { location };
} }
getPageTitle() { getPageTitle() {
const { location } = this.props; const { getRouteData, location } = this.props;
const { pathname } = location; const { pathname } = location;
let title = 'Ant Design Pro'; let title = 'Ant Design Pro';
getRouteData('UserLayout').forEach((item) => { getRouteData('UserLayout').forEach((item) => {
...@@ -39,16 +38,9 @@ class UserLayout extends React.PureComponent { ...@@ -39,16 +38,9 @@ class UserLayout extends React.PureComponent {
}); });
return title; return title;
} }
getRouteComponent(item) {
if (this.routeComponents[item.path]) {
return this.routeComponents[item.path];
}
const component = item.component(this.props.app);
this.routeComponents[item.path] = component;
return component;
}
routeComponents = {};
render() { render() {
const { getRouteData } = this.props;
return ( return (
<DocumentTitle title={this.getPageTitle()}> <DocumentTitle title={this.getPageTitle()}>
<div className={styles.container}> <div className={styles.container}>
...@@ -68,7 +60,7 @@ class UserLayout extends React.PureComponent { ...@@ -68,7 +60,7 @@ class UserLayout extends React.PureComponent {
exact={item.exact} exact={item.exact}
key={item.path} key={item.path}
path={item.path} path={item.path}
component={this.getRouteComponent()} component={item.component}
/> />
) )
) )
......
...@@ -3,31 +3,59 @@ import { Router, Route, Switch } from 'dva/router'; ...@@ -3,31 +3,59 @@ import { Router, Route, Switch } from 'dva/router';
import { LocaleProvider, Spin } from 'antd'; import { LocaleProvider, Spin } from 'antd';
import zhCN from 'antd/lib/locale-provider/zh_CN'; import zhCN from 'antd/lib/locale-provider/zh_CN';
import dynamic from 'dva/dynamic'; import dynamic from 'dva/dynamic';
import cloneDeep from 'lodash/cloneDeep';
import { getNavData } from './common/nav';
import { getPlainNode } from './utils/utils';
import styles from './index.less'; import styles from './index.less';
dynamic.setDefaultLoadingComponent(() => { dynamic.setDefaultLoadingComponent(() => {
return <Spin size="large" className={styles.globalSpin} />; return <Spin size="large" className={styles.globalSpin} />;
}); });
function getRouteData(navData, path) {
if (!navData.some(item => item.layout === path) ||
!(navData.filter(item => item.layout === path)[0].children)) {
return null;
}
const route = cloneDeep(navData.filter(item => item.layout === path)[0]);
const nodeList = getPlainNode(route.children);
return nodeList;
}
function getLayout(navData, path) {
if (!navData.some(item => item.layout === path) ||
!(navData.filter(item => item.layout === path)[0].children)) {
return null;
}
const route = navData.filter(item => item.layout === path)[0];
return {
component: route.component,
layout: route.layout,
name: route.name,
path: route.path,
};
}
function RouterConfig({ history, app }) { function RouterConfig({ history, app }) {
const BasicLayout = dynamic({ const navData = getNavData(app);
app, const UserLayout = getLayout(navData, 'UserLayout').component;
models: () => [ const BasicLayout = getLayout(navData, 'BasicLayout').component;
import('./models/user'),
], const passProps = {
component: () => import('./layouts/BasicLayout'),
});
const UserLayout = dynamic({
app, app,
component: () => import('./layouts/UserLayout'), navData,
}); getRouteData: (path) => {
return getRouteData(navData, path);
},
};
return ( return (
<LocaleProvider locale={zhCN}> <LocaleProvider locale={zhCN}>
<Router history={history}> <Router history={history}>
<Switch> <Switch>
<Route path="/user" render={props => <UserLayout {...props} app={app} />} /> <Route path="/user" render={props => <UserLayout {...props} {...passProps} />} />
<Route path="/" render={props => <BasicLayout {...props} app={app} />} /> <Route path="/" render={props => <BasicLayout {...props} {...passProps} />} />
</Switch> </Switch>
</Router> </Router>
</LocaleProvider> </LocaleProvider>
......
import moment from 'moment'; import moment from 'moment';
import cloneDeep from 'lodash/cloneDeep';
import navData from '../common/nav';
export function fixedZero(val) { export function fixedZero(val) {
return val * 1 < 10 ? `0${val}` : val; return val * 1 < 10 ? `0${val}` : val;
...@@ -52,7 +49,7 @@ export function getTimeDistance(type) { ...@@ -52,7 +49,7 @@ export function getTimeDistance(type) {
} }
} }
function getPlainNode(nodeList, parentPath = '') { export function getPlainNode(nodeList, parentPath = '') {
const arr = []; const arr = [];
nodeList.forEach((node) => { nodeList.forEach((node) => {
const item = node; const item = node;
...@@ -70,16 +67,6 @@ function getPlainNode(nodeList, parentPath = '') { ...@@ -70,16 +67,6 @@ function getPlainNode(nodeList, parentPath = '') {
return arr; return arr;
} }
export function getRouteData(path) {
if (!navData.some(item => item.layout === path) ||
!(navData.filter(item => item.layout === path)[0].children)) {
return null;
}
const dataList = cloneDeep(navData.filter(item => item.layout === path)[0]);
const nodeList = getPlainNode(dataList.children);
return nodeList;
}
export function digitUppercase(n) { export function digitUppercase(n) {
const fraction = ['', '']; const fraction = ['', ''];
const digit = ['', '', '', '', '', '', '', '', '', '']; const digit = ['', '', '', '', '', '', '', '', '', ''];
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment