为什么在刺激控制器中断开连接

本文最初发表于 Rails Designer

Stimulus 中的断开生命周期方法是三种生命周期方法之一。另外两种是 **initialize** 和 **connect**。当控制器从 DOM 中移除时,会调用断开连接。为此,Stimulus 使用突变观察器来跟踪 DOM 元素。

在断开连接方法中,您可以执行 **拆卸**、清理等操作。执行此操作的原因取决于您的代码,但范围包括防止内存泄漏、维护浏览器性能和防止意外副作用。

让我们看一些例子:

export default class extends Controller {
  connect() {
    this.interval = setInterval(() => {
      console.log("Run, Forrest, run!");
    }, 1000);
  }
}

如果不清除间隔,它将继续在后台运行,从而导致内存泄漏。

export default class extends Controller {
  disconnect() {
    clearInterval(this.interval);
  }
}

或者如果你使用第三方库,如CodeMirror:

import { EditorView } from "@codemirror/view"

export default class extends Controller {
  connect() {
    this.editor = new EditorView();
  }
}

清理很简单:

import { EditorView } from "@codemirror/view"

export default class extends Controller {
  disconnect() {
    this.editor?.destroy();
  }
}

如果没有它,任何新的“this.editor”实例都会保持其自己的状态,并且编辑器的 DOM 元素可能会保留在内存中。

让我们再看一个可能会破坏你的浏览器的漏洞。💥

export default class extends Controller {
  connect() {
    navigator.mediaDevices.getUserMedia({ video: true })
      .then(stream => {
        this.videoStream = stream;
        this.element.srcObject = stream;
      });
  }
}

如果不停止视频流,它们将继续在后台运行。然后,在运行多个实例时,这将导致高 CPU 使用率,并可能由于资源不足而导致浏览器崩溃。😬

我们来添加一个断开连接,可以吗?

export default class extends Controller {
  disconnect() {
    this.videoStream.getTracks().forEach(track => track.stop());
  }
}