1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-07-25 06:14:50 +02:00

fix(frontend): いくつかのイベントリスナーの解除処理の修正 (#17768)

* fix(frontend): いくつかのイベントリスナーの解除処理の修正

* fix
This commit is contained in:
かっこかり
2026-07-22 22:28:01 +09:00
committed by GitHub
parent 170ee2bfeb
commit 79b4a73679
5 changed files with 61 additions and 19 deletions

View File

@@ -182,6 +182,9 @@ onMounted(() => {
onUnmounted(() => {
if (connection) connection.dispose();
if (scrollContainer != null) {
scrollContainer.removeEventListener('scroll', onScrollContainerScroll);
}
});
defineExpose({

View File

@@ -37,29 +37,41 @@ const observer = new ResizeObserver((entries) => {
</script>
<script setup lang="ts">
import { ref, watch } from 'vue';
import { onBeforeUnmount, useTemplateRef, watch } from 'vue';
const props = withDefaults(defineProps<Props>(), {
minScale: 0,
});
const content = ref<HTMLSpanElement>();
const content = useTemplateRef('content');
function unobserve(el: HTMLSpanElement | null) {
if (el != null) {
delete (el as any)[contentSymbol];
observer.unobserve(el);
if (el.parentElement) {
observer.unobserve(el.parentElement);
}
}
}
function observe(el: HTMLSpanElement | null) {
if (el != null) {
(el as any)[contentSymbol] = props;
observer.observe(el);
if (el.parentElement) {
observer.observe(el.parentElement);
}
}
}
watch(content, (value, oldValue) => {
if (oldValue != null) {
delete (oldValue as any)[contentSymbol];
observer.unobserve(oldValue);
if (oldValue.parentElement) {
observer.unobserve(oldValue.parentElement);
}
}
if (value != null) {
(value as any)[contentSymbol] = props;
observer.observe(value);
if (value.parentElement) {
observer.observe(value.parentElement);
}
}
unobserve(oldValue);
observe(value);
});
onBeforeUnmount(() => {
unobserve(content.value);
});
</script>

View File

@@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script setup lang="ts">
import { computed, onMounted, ref, toRefs, useTemplateRef, watch } from 'vue';
import { computed, onMounted, onUnmounted, ref, toRefs, useTemplateRef, watch } from 'vue';
import type { DataSource, GridSetting, GridState, Size } from '@/components/grid/grid.js';
import type { CellAddress, CellValue, GridCell } from '@/components/grid/cell.js';
import type { GridContext, GridEvent } from '@/components/grid/grid-event.js';
@@ -119,6 +119,10 @@ const { data } = toRefs(props);
* 子コンポーネント -> gridのイベントでは原則使用せず、{@link emit}を使用する。
*/
const bus = new GridEventEmitter();
/**
* {@link resizeObserver}が発行した、まだ実行されていない{@link setTimeout}のID。アンマウント時にまとめて破棄するために保持する。
*/
const resizeTimeoutIds = new Set<number>();
/**
* テーブルコンポーネントのリサイズイベントを監視するための{@link ResizeObserver}。
* 表示切替を検知し、サイズの再計算要求を発行するために使用する(マウント時にコンテンツが表示されていない場合、初手のサイズの自動計算が正常に働かないため)
@@ -128,7 +132,13 @@ const bus = new GridEventEmitter();
*
* @see {@link onResize}
*/
const resizeObserver = new ResizeObserver((entries) => window.setTimeout(() => onResize(entries)));
const resizeObserver = new ResizeObserver((entries) => {
const timeoutId = window.setTimeout(() => {
resizeTimeoutIds.delete(timeoutId);
onResize(entries);
});
resizeTimeoutIds.add(timeoutId);
});
const rootEl = useTemplateRef('rootEl');
/**
@@ -1265,6 +1275,18 @@ onMounted(() => {
refreshData();
});
onUnmounted(() => {
resizeObserver.disconnect();
for (const timeoutId of resizeTimeoutIds) {
window.clearTimeout(timeoutId);
}
resizeTimeoutIds.clear();
// 選択操作の途中でアンマウントされた場合、windowに登録したままのリスナーが残ってしまうので解除しておく
unregisterMouseMove();
unregisterMouseUp();
});
</script>
<style module lang="scss">

View File

@@ -29,7 +29,7 @@ export const clickAnimeDirective = {
target.addEventListener('mouseleave', () => {
target.classList.remove('_anime_bounce_ready');
});
}, { once: true, signal: abortController.signal });
}, { signal: abortController.signal });
el.addEventListener('click', () => {

View File

@@ -239,6 +239,11 @@ export async function getSoundDuration(file: string): Promise<number> {
audioEl.remove();
}
}, 100);
audioEl.addEventListener('error', () => {
resolve(0);
window.clearInterval(si);
audioEl.remove();
}, { once: true });
});
}