Просмотр исходного кода

fixed memory leaks and minor refactoring

Torkel Ödegaard 7 лет назад
Родитель
Сommit
36cd73819a

+ 3 - 4
public/app/core/components/colorpicker/SeriesColorPicker.tsx

@@ -23,14 +23,13 @@ export class SeriesColorPicker extends React.Component<SeriesColorPickerProps> {
 
   constructor(props) {
     super(props);
-    this.openColorPicker = this.openColorPicker.bind(this);
   }
 
   componentWillUnmount() {
     this.destroyDrop();
   }
 
-  openColorPicker() {
+  onClickToOpen = () => {
     if (this.colorPickerDrop) {
       this.destroyDrop();
     }
@@ -59,7 +58,7 @@ export class SeriesColorPicker extends React.Component<SeriesColorPickerProps> {
 
     this.colorPickerDrop = drop;
     this.colorPickerDrop.open();
-  }
+  };
 
   closeColorPicker() {
     setTimeout(() => {
@@ -77,7 +76,7 @@ export class SeriesColorPicker extends React.Component<SeriesColorPickerProps> {
   render() {
     const { optionalClass, children } = this.props;
     return (
-      <div className={optionalClass} ref={e => (this.pickerElem = e)} onClick={this.openColorPicker}>
+      <div className={optionalClass} ref={e => (this.pickerElem = e)} onClick={this.onClickToOpen}>
         {children}
       </div>
     );

+ 1 - 0
public/app/features/dashboard/panel_model.ts

@@ -133,6 +133,7 @@ export class PanelModel {
   }
 
   destroy() {
+    this.events.emit('panel-teardown');
     this.events.removeAllListeners();
   }
 }

+ 0 - 5
public/app/features/panel/panel_ctrl.ts

@@ -48,11 +48,6 @@ export class PanelCtrl {
     }
 
     $scope.$on('component-did-mount', () => this.panelDidMount());
-
-    $scope.$on('$destroy', () => {
-      this.events.emit('panel-teardown');
-      this.events.removeAllListeners();
-    });
   }
 
   panelDidMount() {

+ 19 - 20
public/app/plugins/panel/graph/graph.ts

@@ -38,6 +38,7 @@ class GraphElement {
   panelWidth: number;
   eventManager: EventManager;
   thresholdManager: ThresholdManager;
+  legendElem: HTMLElement;
 
   constructor(private scope, private elem, private timeSrv) {
     this.ctrl = scope.ctrl;
@@ -53,7 +54,7 @@ class GraphElement {
     });
 
     // panel events
-    this.ctrl.events.on('panel-teardown', this.onPanelteardown.bind(this));
+    this.ctrl.events.on('panel-teardown', this.onPanelTeardown.bind(this));
 
     /**
      * Split graph rendering into two parts.
@@ -69,13 +70,11 @@ class GraphElement {
     appEvents.on('graph-hover-clear', this.onGraphHoverClear.bind(this), scope);
     this.elem.bind('plotselected', this.onPlotSelected.bind(this));
     this.elem.bind('plotclick', this.onPlotClick.bind(this));
-    scope.$on('$destroy', this.onScopeDestroy.bind(this));
 
-    // Bind legend event handlers once in constructor to avoid unnecessary re-rendering
-    this.ctrl.toggleSeries = this.ctrl.toggleSeries.bind(this.ctrl);
-    this.ctrl.toggleSort = this.ctrl.toggleSort.bind(this.ctrl);
-    this.ctrl.changeSeriesColor = this.ctrl.changeSeriesColor.bind(this.ctrl);
-    this.ctrl.setSeriesAxis = this.ctrl.setSeriesAxis.bind(this.ctrl);
+    // get graph legend element
+    if (this.elem && this.elem.parent) {
+      this.legendElem = this.elem.parent().find('.graph-legend')[0];
+    }
   }
 
   onRender(renderData) {
@@ -97,14 +96,13 @@ class GraphElement {
       hiddenSeries: this.ctrl.hiddenSeries,
       ...legendOptions,
       ...valueOptions,
-      onToggleSeries: this.ctrl.toggleSeries,
-      onToggleSort: this.ctrl.toggleSort,
-      onColorChange: this.ctrl.changeSeriesColor,
-      onToggleAxis: this.ctrl.setSeriesAxis,
+      onToggleSeries: this.ctrl.onToggleSeries,
+      onToggleSort: this.ctrl.onToggleSort,
+      onColorChange: this.ctrl.onColorChange,
+      onToggleAxis: this.ctrl.onToggleAxis,
     };
     const legendReactElem = React.createElement(Legend, legendProps);
-    const legendElem = this.elem.parent().find('.graph-legend');
-    ReactDOM.render(legendReactElem, legendElem[0], () => this.onLegendRenderingComplete());
+    ReactDOM.render(legendReactElem, this.legendElem, () => this.onLegendRenderingComplete());
   }
 
   onLegendRenderingComplete() {
@@ -125,13 +123,20 @@ class GraphElement {
     this.tooltip.show(evt.pos);
   }
 
-  onPanelteardown() {
+  onPanelTeardown() {
     this.thresholdManager = null;
 
     if (this.plot) {
       this.plot.destroy();
       this.plot = null;
     }
+
+    this.tooltip.destroy();
+    this.elem.off();
+    this.elem.remove();
+
+    console.log('react unmount');
+    ReactDOM.unmountComponentAtNode(this.legendElem);
   }
 
   onGraphHoverClear(event, info) {
@@ -179,12 +184,6 @@ class GraphElement {
     }
   }
 
-  onScopeDestroy() {
-    this.tooltip.destroy();
-    this.elem.off();
-    this.elem.remove();
-  }
-
   shouldAbortRender() {
     if (!this.data) {
       return true;

+ 8 - 8
public/app/plugins/panel/graph/module.ts

@@ -243,24 +243,24 @@ class GraphCtrl extends MetricsPanelCtrl {
     }
   }
 
-  changeSeriesColor(series, color) {
+  onColorChange = (series, color) => {
     series.setColor(color);
     this.panel.aliasColors[series.alias] = series.color;
     this.render();
-  }
+  };
 
-  toggleSeries(hiddenSeries) {
+  onToggleSeries = hiddenSeries => {
     this.hiddenSeries = hiddenSeries;
     this.render();
-  }
+  };
 
-  toggleSort(sortBy, sortDesc) {
+  onToggleSort = (sortBy, sortDesc) => {
     this.panel.legend.sort = sortBy;
     this.panel.legend.sortDesc = sortDesc;
     this.render();
-  }
+  };
 
-  setSeriesAxis(info) {
+  onToggleAxis = info => {
     let override = _.find(this.panel.seriesOverrides, { alias: info.alias });
     if (!override) {
       override = { alias: info.alias };
@@ -268,7 +268,7 @@ class GraphCtrl extends MetricsPanelCtrl {
     }
     override.yaxis = info.yaxis;
     this.render();
-  }
+  };
 
   addSeriesOverride(override) {
     this.panel.seriesOverrides.push(override || {});