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

perf(frontend): MkInput/MkSelectの幅調整にResizeObserverを使用するように (#17762)

perf(frontend): MkInput/MkSelectの定期実行の幅調整にResizeObserverを使用するように

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
かっこかり
2026-07-22 10:17:07 +09:00
committed by GitHub
parent 82cca1124f
commit 48216d343e
2 changed files with 39 additions and 29 deletions

View File

@@ -54,7 +54,6 @@ type ModelValueType<T extends SupportedTypes> =
<script lang="ts" setup generic="T extends SupportedTypes = 'text'">
import { onMounted, onUnmounted, nextTick, ref, useTemplateRef, watch, computed, toRefs } from 'vue';
import { throttle, debounce } from 'throttle-debounce';
import { useInterval } from '@@/js/use-interval.js';
import type { InputHTMLAttributes } from 'vue';
import type { SuggestionType } from '@/utility/autocomplete.js';
import MkButton from '@/components/MkButton.vue';
@@ -163,25 +162,27 @@ watch([changed, invalid], ([newChanged, newInvalid]) => {
// このコンポーネントが作成された時、非表示状態である場合がある
// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する
useInterval(() => {
const updatePadding = (entries: ResizeObserverEntry[]) => {
if (inputEl.value == null) return;
if (prefixEl.value) {
if (prefixEl.value.offsetWidth) {
inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + 'px';
for (const entry of entries) {
const width = entry.borderBoxSize[0].inlineSize;
if (width === 0) continue;
if (entry.target === prefixEl.value) {
inputEl.value.style.paddingLeft = width + 'px';
} else if (entry.target === suffixEl.value) {
inputEl.value.style.paddingRight = width + 'px';
}
}
if (suffixEl.value) {
if (suffixEl.value.offsetWidth) {
inputEl.value.style.paddingRight = suffixEl.value.offsetWidth + 'px';
}
}
}, 100, {
immediate: true,
afterMounted: true,
});
};
let paddingObserver: ResizeObserver | null = null;
onMounted(() => {
paddingObserver = new ResizeObserver(updatePadding);
if (prefixEl.value) paddingObserver.observe(prefixEl.value);
if (suffixEl.value) paddingObserver.observe(suffixEl.value);
nextTick(() => {
if (props.autofocus) {
focus();
@@ -194,6 +195,9 @@ onMounted(() => {
});
onUnmounted(() => {
paddingObserver?.disconnect();
paddingObserver = null;
if (autocompleteWorker) {
autocompleteWorker.detach();
}

View File

@@ -69,8 +69,7 @@ export type GetMkSelectValueTypesFromDef<T extends MkSelectItem[]> = T[number] e
</script>
<script lang="ts" setup generic="const ITEMS extends MkSelectItem[], MODELT extends OptionValue">
import { onMounted, nextTick, ref, watch, computed, toRefs, useTemplateRef } from 'vue';
import { useInterval } from '@@/js/use-interval.js';
import { onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs, useTemplateRef } from 'vue';
import type { MenuItem } from '@/types/menu.js';
import * as os from '@/os.js';
@@ -111,25 +110,27 @@ const focus = () => container.value?.focus();
// このコンポーネントが作成された時、非表示状態である場合がある
// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する
useInterval(() => {
const updatePadding = (entries: ResizeObserverEntry[]) => {
if (inputEl.value == null) return;
if (prefixEl.value) {
if (prefixEl.value.offsetWidth) {
inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + 'px';
for (const entry of entries) {
const width = entry.borderBoxSize[0].inlineSize;
if (width === 0) continue;
if (entry.target === prefixEl.value) {
inputEl.value.style.paddingLeft = width + 'px';
} else if (entry.target === suffixEl.value) {
inputEl.value.style.paddingRight = width + 'px';
}
}
if (suffixEl.value) {
if (suffixEl.value.offsetWidth) {
inputEl.value.style.paddingRight = suffixEl.value.offsetWidth + 'px';
}
}
}, 100, {
immediate: true,
afterMounted: true,
});
};
let paddingObserver: ResizeObserver | null = null;
onMounted(() => {
paddingObserver = new ResizeObserver(updatePadding);
if (prefixEl.value) paddingObserver.observe(prefixEl.value);
if (suffixEl.value) paddingObserver.observe(suffixEl.value);
nextTick(() => {
if (autofocus.value) {
focus();
@@ -137,6 +138,11 @@ onMounted(() => {
});
});
onUnmounted(() => {
paddingObserver?.disconnect();
paddingObserver = null;
});
watch([model, () => props.items], () => {
let found: ItemOption | null = null;
for (const item of props.items) {