Pārlūkot izejas kodu

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

WhatAKitty 8 gadi atpakaļ
vecāks
revīzija
31af67c2d0
5 mainītis faili ar 79 papildinājumiem un 89 dzēšanām
  1. 28 34
      src/common/nav.js
  2. 6 17
      src/layouts/BasicLayout.js
  3. 4 12
      src/layouts/UserLayout.js
  4. 40 12
      src/router.js
  5. 1 14
      src/utils/utils.js

+ 28 - 34
src/common/nav.js

@@ -1,7 +1,7 @@
 import dynamic from 'dva/dynamic';
 
-const data = [{
-  component: app => dynamic({
+export const getNavData = app => [{
+  component: dynamic({
     app,
     models: () => [
       import('../models/user'),
@@ -18,7 +18,7 @@ const data = [{
     children: [{
       name: '分析页',
       path: 'analysis',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/chart'),
@@ -28,7 +28,7 @@ const data = [{
     }, {
       name: '监控页',
       path: 'monitor',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/monitor'),
@@ -38,7 +38,7 @@ const data = [{
     }, {
       name: '工作台',
       path: 'workplace',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/project'),
@@ -55,7 +55,7 @@ const data = [{
     children: [{
       name: '基础表单',
       path: 'basic-form',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/form'),
@@ -65,7 +65,7 @@ const data = [{
     }, {
       name: '分步表单',
       path: 'step-form',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/form'),
@@ -74,7 +74,7 @@ const data = [{
       }),
       children: [{
         path: 'confirm',
-        component: app => dynamic({
+        component: dynamic({
           app,
           models: () => [
             import('../models/form'),
@@ -83,7 +83,7 @@ const data = [{
         }),
       }, {
         path: 'result',
-        component: app => dynamic({
+        component: dynamic({
           app,
           models: () => [
             import('../models/form'),
@@ -94,7 +94,7 @@ const data = [{
     }, {
       name: '高级表单',
       path: 'advanced-form',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/form'),
@@ -109,7 +109,7 @@ const data = [{
     children: [{
       name: '查询表格',
       path: 'table-list',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/rule'),
@@ -119,7 +119,7 @@ const data = [{
     }, {
       name: '标准列表',
       path: 'basic-list',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/list'),
@@ -129,7 +129,7 @@ const data = [{
     }, {
       name: '卡片列表',
       path: 'card-list',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/list'),
@@ -139,7 +139,7 @@ const data = [{
     }, {
       name: '搜索列表(项目)',
       path: 'cover-card-list',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/list'),
@@ -149,7 +149,7 @@ const data = [{
     }, {
       name: '搜索列表(应用)',
       path: 'filter-card-list',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/list'),
@@ -159,7 +159,7 @@ const data = [{
     }, {
       name: '搜索列表(文章)',
       path: 'search',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/list'),
@@ -174,7 +174,7 @@ const data = [{
     children: [{
       name: '基础详情页',
       path: 'basic',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/profile'),
@@ -184,7 +184,7 @@ const data = [{
     }, {
       name: '高级详情页',
       path: 'advanced',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/profile'),
@@ -199,14 +199,14 @@ const data = [{
     children: [{
       name: '成功',
       path: 'success',
-      component: app => dynamic({
+      component: dynamic({
         app,
         component: () => import('../routes/Result/Success'),
       }),
     }, {
       name: '失败',
       path: 'fail',
-      component: app => dynamic({
+      component: dynamic({
         app,
         component: () => import('../routes/Result/Error'),
       }),
@@ -218,28 +218,28 @@ const data = [{
     children: [{
       name: '403',
       path: '403',
-      component: app => dynamic({
+      component: dynamic({
         app,
         component: () => import('../routes/Exception/403'),
       }),
     }, {
       name: '404',
       path: '404',
-      component: app => dynamic({
+      component: dynamic({
         app,
         component: () => import('../routes/Exception/404'),
       }),
     }, {
       name: '500',
       path: '500',
-      component: app => dynamic({
+      component: dynamic({
         app,
         component: () => import('../routes/Exception/500'),
       }),
     }],
   }],
 }, {
-  component: app => dynamic({
+  component: dynamic({
     app,
     component: () => import('../layouts/UserLayout'),
   }),
@@ -252,7 +252,7 @@ const data = [{
     children: [{
       name: '登录',
       path: 'login',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/login'),
@@ -262,7 +262,7 @@ const data = [{
     }, {
       name: '注册',
       path: 'register',
-      component: app => dynamic({
+      component: dynamic({
         app,
         models: () => [
           import('../models/register'),
@@ -272,14 +272,14 @@ const data = [{
     }, {
       name: '注册结果',
       path: 'register-result',
-      component: app => dynamic({
+      component: dynamic({
         app,
         component: () => import('../routes/User/RegisterResult'),
       }),
     }],
   }],
 }, {
-  component: app => dynamic({
+  component: dynamic({
     app,
     component: () => import('../layouts/BlankLayout'),
   }),
@@ -291,9 +291,3 @@ const data = [{
     icon: 'book',
   },
 }];
-
-export function getNavData() {
-  return data;
-}
-
-export default data;

+ 6 - 17
src/layouts/BasicLayout.js

@@ -11,8 +11,6 @@ import classNames from 'classnames';
 import HeaderSearch from '../components/HeaderSearch';
 import NoticeIcon from '../components/NoticeIcon';
 import GlobalFooter from '../components/GlobalFooter';
-import { getNavData } from '../common/nav';
-import { getRouteData } from '../utils/utils';
 import NotFound from '../routes/Exception/404';
 import styles from './BasicLayout.less';
 
@@ -48,15 +46,15 @@ class BasicLayout extends React.PureComponent {
   constructor(props) {
     super(props);
     // 把一级 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 = {
       openKeys: this.getDefaultCollapsedSubMenus(props),
     };
   }
   getChildContext() {
-    const { location } = this.props;
+    const { location, navData, getRouteData } = this.props;
     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 breadcrumbNameMap = {};
 
@@ -166,7 +164,7 @@ class BasicLayout extends React.PureComponent {
     });
   }
   getPageTitle() {
-    const { location } = this.props;
+    const { location, getRouteData } = this.props;
     const { pathname } = location;
     let title = 'Ant Design Pro';
     getRouteData('BasicLayout').forEach((item) => {
@@ -203,15 +201,6 @@ class BasicLayout extends React.PureComponent {
     });
     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) => {
     const lastOpenKey = openKeys[openKeys.length - 1];
     const isMainMenu = this.menus.some(
@@ -248,7 +237,7 @@ class BasicLayout extends React.PureComponent {
     }
   }
   render() {
-    const { currentUser, collapsed, fetchingNotices } = this.props;
+    const { currentUser, collapsed, fetchingNotices, getRouteData } = this.props;
 
     const menu = (
       <Menu className={styles.menu} selectedKeys={[]} onClick={this.onMenuClick}>
@@ -361,7 +350,7 @@ class BasicLayout extends React.PureComponent {
                       exact={item.exact}
                       key={item.path}
                       path={item.path}
-                      component={this.getRouteComponent(item)}
+                      component={item.component}
                     />
                   )
                 )

+ 4 - 12
src/layouts/UserLayout.js

@@ -5,7 +5,6 @@ import DocumentTitle from 'react-document-title';
 import { Icon } from 'antd';
 import GlobalFooter from '../components/GlobalFooter';
 import styles from './UserLayout.less';
-import { getRouteData } from '../utils/utils';
 
 const links = [{
   title: '帮助',
@@ -29,7 +28,7 @@ class UserLayout extends React.PureComponent {
     return { location };
   }
   getPageTitle() {
-    const { location } = this.props;
+    const { getRouteData, location } = this.props;
     const { pathname } = location;
     let title = 'Ant Design Pro';
     getRouteData('UserLayout').forEach((item) => {
@@ -39,16 +38,9 @@ class UserLayout extends React.PureComponent {
     });
     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() {
+    const { getRouteData } = this.props;
+
     return (
       <DocumentTitle title={this.getPageTitle()}>
         <div className={styles.container}>
@@ -68,7 +60,7 @@ class UserLayout extends React.PureComponent {
                   exact={item.exact}
                   key={item.path}
                   path={item.path}
-                  component={this.getRouteComponent()}
+                  component={item.component}
                 />
               )
             )

+ 40 - 12
src/router.js

@@ -3,31 +3,59 @@ import { Router, Route, Switch } from 'dva/router';
 import { LocaleProvider, Spin } from 'antd';
 import zhCN from 'antd/lib/locale-provider/zh_CN';
 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';
 
 dynamic.setDefaultLoadingComponent(() => {
   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 }) {
-  const BasicLayout = dynamic({
-    app,
-    models: () => [
-      import('./models/user'),
-    ],
-    component: () => import('./layouts/BasicLayout'),
-  });
-  const UserLayout = dynamic({
+  const navData = getNavData(app);
+  const UserLayout = getLayout(navData, 'UserLayout').component;
+  const BasicLayout = getLayout(navData, 'BasicLayout').component;
+
+  const passProps = {
     app,
-    component: () => import('./layouts/UserLayout'),
-  });
+    navData,
+    getRouteData: (path) => {
+      return getRouteData(navData, path);
+    },
+  };
 
   return (
     <LocaleProvider locale={zhCN}>
       <Router history={history}>
         <Switch>
-          <Route path="/user" render={props => <UserLayout {...props} app={app} />} />
-          <Route path="/" render={props => <BasicLayout {...props} app={app} />} />
+          <Route path="/user" render={props => <UserLayout {...props} {...passProps} />} />
+          <Route path="/" render={props => <BasicLayout {...props} {...passProps} />} />
         </Switch>
       </Router>
     </LocaleProvider>

+ 1 - 14
src/utils/utils.js

@@ -1,7 +1,4 @@
 import moment from 'moment';
-import cloneDeep from 'lodash/cloneDeep';
-import navData from '../common/nav';
-
 
 export function fixedZero(val) {
   return val * 1 < 10 ? `0${val}` : val;
@@ -52,7 +49,7 @@ export function getTimeDistance(type) {
   }
 }
 
-function getPlainNode(nodeList, parentPath = '') {
+export function getPlainNode(nodeList, parentPath = '') {
   const arr = [];
   nodeList.forEach((node) => {
     const item = node;
@@ -70,16 +67,6 @@ function getPlainNode(nodeList, parentPath = '') {
   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) {
   const fraction = ['角', '分'];
   const digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];