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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user