jim 7 лет назад
Родитель
Сommit
0a3865826b

+ 5 - 3
package.json

@@ -23,7 +23,9 @@
   "dependencies": {
     "@antv/data-set": "^0.8.0",
     "@babel/polyfill": "^7.0.0-beta.36",
-    "antd": "^3.3.3",
+    "@types/react": "^16.3.5",
+    "@types/react-dom": "^16.0.4",
+    "antd": "^3.4.0",
     "babel-runtime": "^6.9.2",
     "bizcharts": "^3.1.3-beta.1",
     "bizcharts-plugin-slider": "^2.0.1",
@@ -40,10 +42,10 @@
     "prop-types": "^15.5.10",
     "qs": "^6.5.0",
     "rc-drawer-menu": "^0.5.0",
-    "react": "^16.2.0",
+    "react": "^16.3.1",
     "react-container-query": "^0.9.1",
     "react-document-title": "^2.0.3",
-    "react-dom": "^16.2.0",
+    "react-dom": "^16.3.1",
     "react-fittext": "^1.0.0",
     "rollbar": "^2.3.4",
     "url-polyfill": "^1.0.10"

+ 108 - 88
src/components/Login/LoginItem.js

@@ -1,104 +1,124 @@
 import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { Form, Button, Row, Col } from 'antd';
+import { Form, Input, Button, Row, Col } from 'antd';
 import omit from 'omit.js';
 import styles from './index.less';
-import map from './map';
+import ItemMap from './map';
+import LoginContext from './loginContext';
 
 const FormItem = Form.Item;
 
-function generator({ defaultProps, defaultRules, type }) {
-  return WrappedComponent => {
-    return class BasicComponent extends Component {
-      static contextTypes = {
-        form: PropTypes.object,
-        updateActive: PropTypes.func,
-      };
-      constructor(props) {
-        super(props);
-        this.state = {
-          count: 0,
-        };
-      }
-      componentDidMount() {
-        if (this.context.updateActive) {
-          this.context.updateActive(this.props.name);
-        }
-      }
-      componentWillUnmount() {
+class WarpFormItem extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      count: 0,
+    };
+  }
+  componentDidMount() {
+    if (this.props.updateActive) {
+      this.props.updateActive(this.props.name);
+    }
+  }
+  componentWillUnmount() {
+    clearInterval(this.interval);
+  }
+  onGetCaptcha = () => {
+    let count = 59;
+    this.setState({ count });
+    if (this.props.onGetCaptcha) {
+      this.props.onGetCaptcha();
+    }
+    this.interval = setInterval(() => {
+      count -= 1;
+      this.setState({ count });
+      if (count === 0) {
         clearInterval(this.interval);
       }
-      onGetCaptcha = () => {
-        let count = 59;
-        this.setState({ count });
-        if (this.props.onGetCaptcha) {
-          this.props.onGetCaptcha();
-        }
-        this.interval = setInterval(() => {
-          count -= 1;
-          this.setState({ count });
-          if (count === 0) {
-            clearInterval(this.interval);
-          }
-        }, 1000);
-      };
-      render() {
-        const { getFieldDecorator } = this.context.form;
-        const options = {};
-        let otherProps = {};
-        const { onChange, defaultValue, rules, name, ...restProps } = this.props;
-        const { count } = this.state;
-        options.rules = rules || defaultRules;
-        if (onChange) {
-          options.onChange = onChange;
-        }
-        if (defaultValue) {
-          options.initialValue = defaultValue;
-        }
-        otherProps = restProps || otherProps;
-        if (type === 'Captcha') {
-          const inputProps = omit(otherProps, ['onGetCaptcha']);
-          return (
-            <FormItem>
-              <Row gutter={8}>
-                <Col span={16}>
-                  {getFieldDecorator(name, options)(
-                    <WrappedComponent {...defaultProps} {...inputProps} />
-                  )}
-                </Col>
-                <Col span={8}>
-                  <Button
-                    disabled={count}
-                    className={styles.getCaptcha}
-                    size="large"
-                    onClick={this.onGetCaptcha}
-                  >
-                    {count ? `${count} s` : '获取验证码'}
-                  </Button>
-                </Col>
-              </Row>
-            </FormItem>
-          );
-        }
-        return (
-          <FormItem>
-            {getFieldDecorator(name, options)(
-              <WrappedComponent {...defaultProps} {...otherProps} />
-            )}
-          </FormItem>
-        );
-      }
+    }, 1000);
+  };
+  getFormItemOptions = ({ onChange, defaultValue, rules }) => {
+    const options = {
+      rules: rules || this.customprops.rules,
     };
+    if (onChange) {
+      options.onChange = onChange;
+    }
+    if (defaultValue) {
+      options.initialValue = defaultValue;
+    }
+    return options;
   };
+  render() {
+    const { count } = this.state;
+
+    const { getFieldDecorator } = this.props.form;
+
+    // 这么写是为了防止restProps中 带入 onChange, defaultValue, rules props
+    const {
+      onChange,
+      customprops,
+      defaultValue,
+      rules,
+      name,
+      updateActive,
+      ...restProps
+    } = this.props;
+
+    // get getFieldDecorator props
+    const options = this.getFormItemOptions(this.props);
+
+    const otherProps = restProps || {};
+    if (this.props.type === 'Captcha') {
+      const inputProps = omit(otherProps, ['onGetCaptcha']);
+      return (
+        <FormItem>
+          <Row gutter={8}>
+            <Col span={16}>
+              {getFieldDecorator(name, options)(
+                <Input {...this.props.customprops} {...inputProps} />
+              )}
+            </Col>
+            <Col span={8}>
+              <Button
+                disabled={count}
+                className={styles.getCaptcha}
+                size="large"
+                onClick={this.onGetCaptcha}
+              >
+                {count ? `${count} s` : '获取验证码'}
+              </Button>
+            </Col>
+          </Row>
+        </FormItem>
+      );
+    }
+    return (
+      <FormItem>
+        {getFieldDecorator(name, options)(<Input {...this.props.customprops} {...otherProps} />)}
+      </FormItem>
+    );
+  }
 }
 
 const LoginItem = {};
-Object.keys(map).forEach(item => {
-  LoginItem[item] = generator({
-    defaultProps: map[item].props,
-    defaultRules: map[item].rules,
-    type: item,
-  })(map[item].component);
+Object.keys(ItemMap).forEach(key => {
+  const item = ItemMap[key];
+  LoginItem[key] = props => {
+    return (
+      <LoginContext.Consumer>
+        {context => (
+          <WarpFormItem
+            customprops={item.props}
+            {...props}
+            rules={item.rules}
+            type={key}
+            updateActive={context.updateActive}
+            form={context.form}
+          />
+        )}
+      </LoginContext.Consumer>
+    );
+  };
 });
 
 export default LoginItem;

+ 13 - 10
src/components/Login/LoginTab.js

@@ -1,6 +1,6 @@
 import React, { Component } from 'react';
-import PropTypes from 'prop-types';
 import { Tabs } from 'antd';
+import LoginContext from './loginContext';
 
 const { TabPane } = Tabs;
 
@@ -12,21 +12,24 @@ const generateId = (() => {
   };
 })();
 
-export default class LoginTab extends Component {
-  static __ANT_PRO_LOGIN_TAB = true;
-  static contextTypes = {
-    tabUtil: PropTypes.object,
-  };
+class LoginTab extends Component {
   constructor(props) {
     super(props);
     this.uniqueId = generateId('login-tab-');
   }
-  componentWillMount() {
-    if (this.context.tabUtil) {
-      this.context.tabUtil.addTab(this.uniqueId);
-    }
+  componentDidMount() {
+    this.props.tabUtil.addTab(this.uniqueId);
   }
   render() {
     return <TabPane {...this.props} />;
   }
 }
+
+const warpContext = props => {
+  return (
+    <LoginContext.Consumer>
+      {value => <LoginTab tabUtil={value.tabUtil} {...props} />}
+    </LoginContext.Consumer>
+  );
+};
+export default warpContext;

+ 30 - 32
src/components/Login/index.js

@@ -6,6 +6,7 @@ import LoginItem from './LoginItem';
 import LoginTab from './LoginTab';
 import LoginSubmit from './LoginSubmit';
 import styles from './index.less';
+import LoginContext from './loginContext';
 
 @Form.create()
 class Login extends Component {
@@ -21,17 +22,18 @@ class Login extends Component {
     onTabChange: PropTypes.func,
     onSubmit: PropTypes.func,
   };
-  static childContextTypes = {
-    tabUtil: PropTypes.object,
-    form: PropTypes.object,
-    updateActive: PropTypes.func,
-  };
   state = {
     type: this.props.defaultActiveKey,
     tabs: [],
     active: {},
   };
-  getChildContext() {
+  onSwitch = type => {
+    this.setState({
+      type,
+    });
+    this.props.onTabChange(type);
+  };
+  getContext = () => {
     return {
       tabUtil: {
         addTab: id => {
@@ -58,12 +60,6 @@ class Login extends Component {
         });
       },
     };
-  }
-  onSwitch = type => {
-    this.setState({
-      type,
-    });
-    this.props.onTabChange(type);
   };
   handleSubmit = e => {
     e.preventDefault();
@@ -83,32 +79,34 @@ class Login extends Component {
         return;
       }
       // eslint-disable-next-line
-      if (item.type.__ANT_PRO_LOGIN_TAB) {
+      if (item.type.name === 'warpContext') {
         TabChildren.push(item);
       } else {
         otherChildren.push(item);
       }
     });
     return (
-      <div className={classNames(className, styles.login)}>
-        <Form onSubmit={this.handleSubmit}>
-          {tabs.length ? (
-            <div>
-              <Tabs
-                animated={false}
-                className={styles.tabs}
-                activeKey={type}
-                onChange={this.onSwitch}
-              >
-                {TabChildren}
-              </Tabs>
-              {otherChildren}
-            </div>
-          ) : (
-            [...children]
-          )}
-        </Form>
-      </div>
+      <LoginContext.Provider value={this.getContext()}>
+        <div className={classNames(className, styles.login)}>
+          <Form onSubmit={this.handleSubmit}>
+            {tabs.length ? (
+              <>
+                <Tabs
+                  animated={false}
+                  className={styles.tabs}
+                  activeKey={type}
+                  onChange={this.onSwitch}
+                >
+                  {TabChildren}
+                </Tabs>
+                {otherChildren}
+              </>
+            ) : (
+              [...children]
+            )}
+          </Form>
+        </div>
+      </LoginContext.Provider>
     );
   }
 }

+ 4 - 0
src/components/Login/loginContext.js

@@ -0,0 +1,4 @@
+import { createContext } from 'react';
+
+const LoginContext = createContext();
+export default LoginContext;

+ 2 - 8
src/components/Login/map.js

@@ -1,10 +1,9 @@
 import React from 'react';
-import { Input, Icon } from 'antd';
+import { Icon } from 'antd';
 import styles from './index.less';
 
-const map = {
+export default {
   UserName: {
-    component: Input,
     props: {
       size: 'large',
       prefix: <Icon type="user" className={styles.prefixIcon} />,
@@ -18,7 +17,6 @@ const map = {
     ],
   },
   Password: {
-    component: Input,
     props: {
       size: 'large',
       prefix: <Icon type="lock" className={styles.prefixIcon} />,
@@ -33,7 +31,6 @@ const map = {
     ],
   },
   Mobile: {
-    component: Input,
     props: {
       size: 'large',
       prefix: <Icon type="mobile" className={styles.prefixIcon} />,
@@ -51,7 +48,6 @@ const map = {
     ],
   },
   Captcha: {
-    component: Input,
     props: {
       size: 'large',
       prefix: <Icon type="mail" className={styles.prefixIcon} />,
@@ -65,5 +61,3 @@ const map = {
     ],
   },
 };
-
-export default map;