Кожен computed, watch і watchEffect, створений у setup компонента, Vue автоматично прив'язує до компонента і зупиняє, коли компонент знищується. Поза компонентом такої прив'язки немає - ефекти живуть, доки їх не зупинити вручну.
effectScope збирає всі ефекти, створені всередині, в одну групу, яку можна зупинити одним викликом:
import { effectScope, ref, watch, computed } from 'vue';
const scope = effectScope();
scope.run(() => {
const query = ref('');
const results = computed(() => search(query.value));
watch(query, (value) => saveToHistory(value));
watchEffect(() => console.log(results.value.length));
});
// пізніше - зупинити все разом
scope.stop();
Де це потрібно:
1. Спільний стан composable для кількох компонентів («спільний composable»): ефекти мають жити, поки є хоча б один споживач, і зупинитися, коли зник останній:
function createSharedComposable(factory) {
let consumers = 0;
let state, scope;
return () => {
consumers++;
if (!state) {
scope = effectScope(true); // detached: не прив'язаний до поточного компонента
state = scope.run(factory);
}
onScopeDispose(() => {
if (--consumers === 0) {
scope.stop();
state = scope = undefined;
}
});
return state;
};
}
Саме так влаштований createSharedComposable у VueUse.
2. Бібліотеки й сховища. Pinia створює effectScope для кожного стора - тому $dispose() прибирає всі його спостерігачі.
3. Тести - ізолювати й гарантовано прибрати ефекти між тестами.
4. Тимчасові ефекти - наприклад, на час відкритого модального вікна чи активного режиму редагування.
onScopeDispose(fn) - реєструє очищення для поточної області: в компоненті спрацює при його знищенні, в effectScope - при stop(). Тому composable, що використовує onScopeDispose замість onUnmounted, працює і в компонентах, і поза ними.
getCurrentScope() - дізнатися, чи код виконується всередині області (наприклад, щоб composable попередив, що його викликали поза компонентом).
Без цього composable, викликаний поза setup (у сторі, в роутері, в модулі), створює спостерігачів, які ніколи не зупиняться, - витоки пам'яті в довгоживучих SPA.