はじめに
Vuetifyのコンポーネントにv-autocompleteというものがあります。
このコンポーネントのフォーカスが外れるタイミングを検知したかったのですが、Blurのイベントはv-autocomplete内のv-selectに該当する機能ではなく、入力部分に対して掛かってしまっているようでした。
https://github.com/vuetifyjs/vuetify/issues/11066
そのため、実際にv-autocompleteのフォーカスを監視するために、MutationObserverAPIを利用してclassの監視をしていたのですが、Vuetifyにはv-mutateディレクティブが存在していることに気が付き、使ってみました。
※Nuxt+CompositionApiの記述になってしまっているので、ご了承ください。
MutationObserverによる実装
<v-autocomplete
ref="autocomplete"
/>
// $refsでv-autocompleteを監視
const autocomplete = ref<Vue>()
// Observerを生成
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.attributeName) {
const className = (mutation.target as Element).getAttribute(mutation.attributeName)
const isFocus = className?.includes('v-input--is-focused') ?? false
// クラスを監視してフォーカス状態を検知!
}
}
})
// マウント時に監視開始し、アンマウント時に監視終了する
onMounted(() => {
if (autocomplete.value) {
observer.observe(autocomplete.value.$el, {
attributes: true,
attributeOldValue: true,
attributeFilter: ['class'],
})
}
})
onUnmounted(() => {
observer.disconnect()
})
マウントしてコンポーネントのrefが取れたらObserverを適用、アンマウント時にdisconnectする必要があります。
v-mutateによる実装
<v-autocomplete
v-mutate.attr="{
handler: onMutate,
options: {
attributeOldValue: true,
attributeFilter: ['class'],
},
}"
/>
const onMutate = (mutationsList: any) => {
for (const mutation of mutationsList) {
if (mutation.attributeName) {
const className = (mutation.target as Element).getAttribute(mutation.attributeName)
const isFocus = className?.includes('v-input--is-focused') ?? false
// クラスを監視してフォーカス状態を検知!
}
}
}
関数を渡すだけでシンプルになりました。
また、refではHTML側だけで読み取れる情報が少なくしっかりコードを読み込む必要がありましたが、v-mutateを記述していることにより可読性も上がったように思えます。
おわりに
少しニッチかもしれませんが、誰かの役に立てば幸いです。
他の方法や改善点等あれば教えていただけると嬉しいです。