理由
Vue と React では、両方のフレームワークが仮想 DOM テクノロジーを使用しているため、コンポーネントが破棄された後もタイマーが実行され続ける場合があります。仮想 DOM はレンダリングの効率とパフォーマンスを向上させますが、いくつかの問題も引き起こします。
Vue/React コンポーネントでタイマーを作成するときは、実際にコンポーネントのライフサイクル メソッド ( またはmounted
など)componentDidMount
にタイマーを登録します。これは、コンポーネントが破棄されると、そのコンポーネントはページ上に表示されなくなりますが、登録されたタイマーを含め、コンポーネント インスタンスがメモリ内にまだ存在することを意味します。
JavaScript のガベージ コレクションは自動プロセスであり、リサイクルのタイミングはガベージ コレクション メカニズム自体によって制御されるためです。オブジェクトが参照されなくなった場合、そのオブジェクトは、ガベージ コレクション メカニズムによって到達不可能であると判断されるまで、一定期間メモリ内に残ることがあります。
リサイクルの具体的なタイミングは、オペレーティング システム、ブラウザ、ガベージ コレクション メカニズム自体の実装によって異なります。一般に、このプロセスは透過的であり、開発者はそれを正確に制御できません。
コンポーネントのライフサイクル メソッドでタイマーを手動でクリアしない場合、コンポーネントが破棄された後もタイマーは実行され続けます。この時点ではコンポーネント インスタンスがページ上に存在しないため、仮想 DOM はタイマーの状態を監視できません。変化。これにより、ページ全体が閉じるか更新されるまで、タイマーがメモリと CPU リソースを占有します。
解決
これを回避するには、コンポーネントが破棄されたときに、コンポーネント内で作成されたタイマーを手動でクリアする必要があります。Vue では、beforeDestroy
ライフサイクル。
<template>
<div>My Component</div>
</template>
<script>
import { onMounted, onUnmounted } from 'vue';
export default {
setup() {
let timerId = null;
onMounted(() => {
timerId = setInterval(() => {
console.log('tick');
}, 1000);
});
onUnmounted(() => {
clearInterval(timerId);
});
},
};
</script>
React では、componentWillUnmount
ライフサイクル。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.timerId = null;
}
componentDidMount() {
this.timerId = setInterval(() => {
console.log('tick');
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timerId);
}
render() {
return <div>My Component</div>;
}
}