From 8ec9ad0cb395cb9302620ccc93a3fd4272e37524 Mon Sep 17 00:00:00 2001 From: liaoxuezhi Date: Sun, 15 Dec 2019 17:38:04 +0800 Subject: [PATCH] =?UTF-8?q?store=20=E5=9B=9E=E6=94=B6=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 - src/renderers/Form/Combo.tsx | 6 +- src/renderers/Form/Control.tsx | 100 ++++++++++++++++----------------- src/renderers/Form/index.tsx | 93 +++++++++++++++--------------- src/renderers/Video.tsx | 22 ++++---- src/store/iRenderer.ts | 29 +++++++++- src/store/index.ts | 8 ++- 7 files changed, 144 insertions(+), 115 deletions(-) diff --git a/package.json b/package.json index a126b9d0..b17e6523 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,6 @@ "react-addons-update": "15.6.2", "react-color": "2.13.8", "react-cropper": "1.0.0", - "react-date-range": "0.9.4", "react-datetime": "2.16.0", "react-dom": "^16.8.6", "react-dropzone": "10.1.10", diff --git a/src/renderers/Form/Combo.tsx b/src/renderers/Form/Combo.tsx index 7cc928a2..1e565e7d 100644 --- a/src/renderers/Form/Combo.tsx +++ b/src/renderers/Form/Combo.tsx @@ -734,7 +734,7 @@ export default class ComboControl extends React.Component { wrapWithPanel: false, mode: subFormMode, className: cx(`Combo-form`, formClassName), - lazyOnChange: false + lazyChange: false }, { index, @@ -907,7 +907,7 @@ export default class ComboControl extends React.Component { wrapWithPanel: false, mode: multiLine ? subFormMode : 'row', className: cx(`Combo-form`, formClassName), - lazyOnChange: false + lazyChange: false }, { index, @@ -1043,7 +1043,7 @@ export default class ComboControl extends React.Component { wrapWithPanel: false, mode: multiLine ? 'normal' : 'row', className: cx(`Combo-form`, formClassName), - lazyOnChange: false + lazyChange: false }, { disabled: disabled, diff --git a/src/renderers/Form/Control.tsx b/src/renderers/Form/Control.tsx index a5f5da75..e5d6e3be 100644 --- a/src/renderers/Form/Control.tsx +++ b/src/renderers/Form/Control.tsx @@ -52,8 +52,14 @@ export default class FormControl extends React.PureComponent< static defaultProps = {}; - lazyValidate: Function; - lazyEmitChange: (submitOnChange: boolean) => void; + lazyValidate = debouce(this.validate.bind(this), 250, { + trailing: true, + leading: false + }); + lazyEmitChange = debouce(this.emitChange.bind(this), 250, { + trailing: true, + leading: false + }); state = {value: this.props.control.value}; componentWillMount() { const { @@ -83,14 +89,6 @@ export default class FormControl extends React.PureComponent< this.setPrinstineValue = this.setPrinstineValue.bind(this); this.controlRef = this.controlRef.bind(this); this.handleBlur = this.handleBlur.bind(this); - this.lazyValidate = debouce(this.validate.bind(this), 250, { - trailing: true, - leading: false - }); - this.lazyEmitChange = debouce(this.emitChange.bind(this), 250, { - trailing: true, - leading: false - }); if (!name) { return; @@ -165,43 +163,43 @@ export default class FormControl extends React.PureComponent< const props = this.props; const form = nextProps.formStore; - if (!nextProps.control.name) { - // 把 name 删了, 对 model 做清理 - this.model && this.disposeModel(); - this.reaction && this.reaction(); - this.model = undefined; - return; - } else if (nextProps.control.name !== props.control.name || !this.model) { - // 对 model 做清理 - this.model && this.disposeModel(); - this.reaction && this.reaction(); + // if (!nextProps.control.name) { + // // 把 name 删了, 对 model 做清理 + // this.model && this.disposeModel(); + // this.reaction && this.reaction(); + // this.model = undefined; + // return; + // } else if (nextProps.control.name !== props.control.name || !this.model) { + // // 对 model 做清理 + // this.model && this.disposeModel(); + // this.reaction && this.reaction(); - // name 是后面才有的,比如编辑模式下就会出现。 - const model = (this.model = form.registryItem(nextProps.control.name, { - id: nextProps.control.id, - type: nextProps.control.type, - required: nextProps.control.required, - unique: nextProps.control.unique, - value: nextProps.control.value, - rules: nextProps.control.validations, - multiple: nextProps.control.multiple, - delimiter: nextProps.control.delimiter, - valueField: nextProps.control.valueField, - labelField: nextProps.control.labelField, - joinValues: nextProps.control.joinValues, - extractValue: nextProps.control.extractValue, - messages: nextProps.control.validationErrors - })); - // this.forceUpdate(); - this.setState({ - value: model.value - }); + // // name 是后面才有的,比如编辑模式下就会出现。 + // const model = (this.model = form.registryItem(nextProps.control.name, { + // id: nextProps.control.id, + // type: nextProps.control.type, + // required: nextProps.control.required, + // unique: nextProps.control.unique, + // value: nextProps.control.value, + // rules: nextProps.control.validations, + // multiple: nextProps.control.multiple, + // delimiter: nextProps.control.delimiter, + // valueField: nextProps.control.valueField, + // labelField: nextProps.control.labelField, + // joinValues: nextProps.control.joinValues, + // extractValue: nextProps.control.extractValue, + // messages: nextProps.control.validationErrors + // })); + // // this.forceUpdate(); + // this.setState({ + // value: model.value + // }); - this.reaction = reaction( - () => model.value, - value => this.setState({value}) - ); - } + // this.reaction = reaction( + // () => model.value, + // value => this.setState({value}) + // ); + // } if ( this.model && @@ -268,10 +266,11 @@ export default class FormControl extends React.PureComponent< componentWillUnmount() { this.hook && this.props.removeHook(this.hook); this.hook2 && this.props.removeHook(this.hook2); - this.disposeModel(); + this.lazyValidate.cancel(); + // this.lazyEmitChange.flush(); + this.lazyEmitChange.cancel(); this.reaction && this.reaction(); - (this.lazyValidate as any).cancel(); - (this.lazyEmitChange as any).cancel(); + this.disposeModel(); } disposeModel() { @@ -348,7 +347,7 @@ export default class FormControl extends React.PureComponent< const { formStore: form, onChange, - control: {type, pipeOut}, + control: {type, pipeOut, changeImmediately: conrolChangeImmediately}, formInited } = this.props; @@ -368,7 +367,7 @@ export default class FormControl extends React.PureComponent< value }, () => - changeImmediately || !formInited + changeImmediately || conrolChangeImmediately || !formInited ? this.emitChange(submitOnChange) : this.lazyEmitChange(submitOnChange) ); @@ -521,7 +520,6 @@ export default class FormControl extends React.PureComponent< return render('', control, { ...rest, - key: `${control.name || ''}-${control.type}`, // 很重要:如果不写实际的 control 组件变了,但是 this.control 还是引用的原来那个。 defaultSize: controlWidth, disabled: disabled || control.disabled, formItem: model, diff --git a/src/renderers/Form/index.tsx b/src/renderers/Form/index.tsx index 3f31e137..e651a52c 100644 --- a/src/renderers/Form/index.tsx +++ b/src/renderers/Form/index.tsx @@ -152,7 +152,7 @@ export default class Form extends React.Component { 'onFailed', 'onFinished', 'canAccessSuperData', - 'lazyOnChange' + 'lazyChange' ]; hooks: { @@ -163,7 +163,10 @@ export default class Form extends React.Component { shouldLoadInitApi: boolean = false; timer: NodeJS.Timeout; mounted: boolean; - lazyHandleChange: (value: any, name: string, submit: boolean) => void; + lazyHandleChange = debouce(this.handleChange.bind(this), 250, { + trailing: true, + leading: false + }); constructor(props: FormProps) { super(props); @@ -179,10 +182,6 @@ export default class Form extends React.Component { this.addHook = this.addHook.bind(this); this.removeHook = this.removeHook.bind(this); this.handleChange = this.handleChange.bind(this); - this.lazyHandleChange = debouce(this.handleChange, 250, { - trailing: true, - leading: false - }); this.renderFormItems = this.renderFormItems.bind(this); this.reload = this.reload.bind(this); this.silentReload = this.silentReload.bind(this); @@ -303,7 +302,8 @@ export default class Form extends React.Component { componentWillUnmount() { this.mounted = false; clearTimeout(this.timer); - (this.lazyHandleChange as any).cancel(); + // this.lazyHandleChange.flush(); + this.lazyHandleChange.cancel(); this.asyncCancel && this.asyncCancel(); this.disposeOnValidate && this.disposeOnValidate(); const store = this.props.store; @@ -896,13 +896,15 @@ export default class Form extends React.Component { disabled, controlWidth, resolveDefinitions, - lazyOnChange + lazyChange } = props; const subProps = { formStore: form, data: store.data, - key, + key: `${(control as Schema).name || ''}-${ + (control as Schema).type + }-${key}`, formInited: form.inited, formMode: mode, formHorizontal: horizontal, @@ -910,8 +912,7 @@ export default class Form extends React.Component { disabled: disabled || (control as Schema).disabled || form.loading, btnDisabled: form.loading || form.validating, onAction: this.handleAction, - onChange: - lazyOnChange !== false ? this.lazyHandleChange : this.handleChange, + onChange: this.lazyHandleChange, addHook: this.addHook, removeHook: this.removeHook, renderFormItems: this.renderFormItems, @@ -919,7 +920,7 @@ export default class Form extends React.Component { }; const subSchema: any = - control && (control as Schema).type === 'control' + (control as Schema).type === 'control' ? control : { type: 'control', @@ -944,6 +945,7 @@ export default class Form extends React.Component { control.hiddenOn && (subSchema.hiddenOn = control.hiddenOn); control.visibleOn && (subSchema.visibleOn = control.visibleOn); + lazyChange === false && (control.changeImmediately = true); } return render(`${region ? `${region}/` : ''}${key}`, subSchema, subProps); @@ -956,46 +958,23 @@ export default class Form extends React.Component { controls, mode, className, - classnames: cx - } = this.props; - - return ( -
- {this.renderFormItems({ - tabs, - fieldSet, - controls - })} -
- ); - } - - render() { - const { - className, - wrapWithPanel, - render, - title, - store, - panelClassName, - debug, - headerClassName, - footerClassName, - actionsClassName, - bodyClassName, - classPrefix: ns, classnames: cx, + debug, $path, - affixFooter, - mode + store, + render } = this.props; const WrapperComponent = this.props.wrapperComponent || (/(?:\/|^)form\//.test($path as string) ? 'div' : 'form'); - let body = ( - + return ( + {debug ? (
             {JSON.stringify(store.data, null, 2)}
@@ -1004,7 +983,11 @@ export default class Form extends React.Component {
 
         
 
-        {this.renderBody()}
+        {this.renderFormItems({
+          tabs,
+          fieldSet,
+          controls
+        })}
 
         {render(
           'modal',
@@ -1039,6 +1022,24 @@ export default class Form extends React.Component {
         )}
       
     );
+  }
+
+  render() {
+    const {
+      wrapWithPanel,
+      render,
+      title,
+      store,
+      panelClassName,
+      headerClassName,
+      footerClassName,
+      actionsClassName,
+      bodyClassName,
+      classnames: cx,
+      affixFooter
+    } = this.props;
+
+    let body: JSX.Element = this.renderBody();
 
     if (wrapWithPanel) {
       body = render(
@@ -1101,6 +1102,8 @@ export class FormRenderer extends Form {
   componentWillUnmount() {
     const scoped = this.context as IScopedContext;
     scoped.unRegisterComponent(this);
+
+    super.componentWillUnmount();
   }
 
   doAction(action: Action, data: object, throwErrors: boolean = false) {
diff --git a/src/renderers/Video.tsx b/src/renderers/Video.tsx
index 271da54c..c6b4e214 100644
--- a/src/renderers/Video.tsx
+++ b/src/renderers/Video.tsx
@@ -42,7 +42,7 @@ export interface FlvSourceProps {
   order?: number;
 }
 
-let currentPlaying: any = null;
+// let currentPlaying: any = null;
 
 export class FlvSource extends React.Component {
   flvPlayer: any;
@@ -262,17 +262,17 @@ export default class Video extends React.Component {
         videoState: state
       });
 
-      if (!state.paused) {
-        if (
-          currentPlaying &&
-          currentPlaying.video &&
-          currentPlaying !== player
-        ) {
-          currentPlaying.pause();
-        }
+      // if (!state.paused) {
+      //   if (
+      //     currentPlaying &&
+      //     currentPlaying.video &&
+      //     currentPlaying !== player
+      //   ) {
+      //     currentPlaying.pause();
+      //   }
 
-        currentPlaying = player;
-      }
+      //   currentPlaying = player;
+      // }
 
       if (!this.frameDom || !this.times) {
         return;
diff --git a/src/store/iRenderer.ts b/src/store/iRenderer.ts
index 368ba446..933d482b 100644
--- a/src/store/iRenderer.ts
+++ b/src/store/iRenderer.ts
@@ -1,4 +1,4 @@
-import {types, getRoot, Instance} from 'mobx-state-tree';
+import {types, getRoot, Instance, destroy} from 'mobx-state-tree';
 import {extendObject, createObject} from '../utils/helper';
 import {IRendererStore} from './index';
 import {dataMapping} from '../utils/tpl-builtin';
@@ -13,7 +13,9 @@ export const iRendererStore = types
     data: types.optional(types.frozen(), {}),
     updatedAt: 0, // 从服务端更新时刻
     pristine: types.optional(types.frozen(), {}),
-    parentId: types.optional(types.string, ''),
+    disposed: false,
+    parentId: '',
+    childrenIds: types.optional(types.array(types.string), []),
     action: types.optional(types.frozen(), undefined),
     dialogOpen: false,
     dialogData: types.optional(types.frozen(), undefined),
@@ -35,6 +37,18 @@ export const iRendererStore = types
   .actions(self => {
     const dialogCallbacks = new SimpleMap<(result?: any) => void>();
 
+    function dispose() {
+      // 先标记自己是要销毁的。
+      self.disposed = true;
+      const parent = self.parentStore;
+
+      if (!self.childrenIds.length) {
+        const id = self.id;
+        destroy(self);
+        parent && parent.onChildDispose(id);
+      }
+    }
+
     return {
       initData(data: object = {}) {
         self.pristine = data;
@@ -152,7 +166,16 @@ export const iRendererStore = types
           dialogCallbacks.delete(self.drawerData);
           setTimeout(() => callback(result), 200);
         }
-      }
+      },
+
+      onChildDispose(childId: string) {
+        const childrenIds = self.childrenIds.filter(item => item !== childId);
+        self.childrenIds.replace(childrenIds);
+
+        self.disposed && dispose();
+      },
+
+      dispose
     };
   });
 
diff --git a/src/store/index.ts b/src/store/index.ts
index 2dc38ca3..962e6d0f 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -68,12 +68,18 @@ export const RendererStore = types
       if (self.stores.has(store.id as string)) {
         return self.stores.get(store.id) as IIRendererStore;
       }
+
+      if (store.parentId) {
+        const parent = self.stores.get(store.parentId) as IIRendererStore;
+        parent.childrenIds.push(store.id);
+      }
+
       self.stores.put(store);
       return self.stores.get(store.id) as IIRendererStore;
     },
 
     removeStore(store: IIRendererStore) {
-      detach(store);
+      store.dispose();
     }
   }));