😶‍🌫️

[Vuetify3] v-overlay をクリックしてもモーダルを閉じたくない

2024/11/22に公開

はじめに

今自分の担当しているプロジェクトは Vue@2 + Vuetify@2 から Vue@3 + Vuetify@3 へのリプレイスを行っています。
キャッチアップしながら実装しているのですが、
各コンポーネント、地味に差分があるので毎度調べながら再現できるよう開発を進めています。

今回は、v-overlay を使ったローディングコンポーネントを作っていた際に対応した内容を
メモとして書き残しておきます。

起きていた現象

ローディングフラグが ON になると v-overlay で囲われた UI が画面全面に表示されます。
そのうち、Vuetify@2 では起きなかったのですが、
Vuetify@3 だと背景のオーバーレイ部分をクリックしたらローディングコンポーネントが閉じてしまう現象が起きたので、それを抑制する対応が必要でした。

結論

結論としては v-overlay にただ persistent をつけるだけでクリックイベントを抑制することが出来ます。

https://vuetifyjs.com/en/api/v-overlay/#props-persistent

<template>
  <v-overlay
    class="d-flex align-center justify-center fill-height"
    :model-value="Loading"
    :scrim="false"
    persistent
  >
    <v-card color="primary">
      <v-card-text>
        Loading...
      </v-card-text>
    </v-card>
  </v-overlay>
</template>

<script setup lang="ts">
import { computed, defineProps } from 'vue'

const props = defineProps<{
  loading: number
}>()

const Loading = computed(() => props.loading > 0)
</script>

ドキュメントには受け取れるイベントハンドラの項目で click:outside もありましたが、
こちらとは別管理の state のため不要でした。

こちらを使いたい場合は、v-overlay@click:outside="handler" という形式で渡すと発火します。

https://vuetifyjs.com/en/api/v-overlay/#events-click:outside

Vuetify@2 との比較

元となるコードのサンプルは以下です。

<template>
  <v-overlay :value="Loading" color="transparent">
    <v-card color="primary">
      <v-card-text>
        Loading...
      </v-card-text>
    </v-card>
  </v-overlay>
</template>

<script setup lang="ts">
import { computed, defineProps } from 'vue'

const props = defineProps<{
  loading: number
}>()

const Loading = computed(() => props.loading > 0)
</script>

Vuetify@2 では特にそのようなプロパティは不要だったのが差分でした。

また、オーバーレイの背景色指定なども破壊的変更が行われており、
Vuetify@2 では color="transparent" としているところなども
:scrim="false" を渡してあげると同じように再現することが出来ました。

まとめ

破壊的変更も多く、地味に class="d-flex align-center justify-center fill-height" としないと中央にカードが来ないパターンや、
背景をクリックするとなぜか UI(v-card) がバウンスするアニメーションを抑えたい場合は、
v-overlayno-click-animation 属性を追加するなど、Vuetify のアップデートには細かい積み重ねが必要です。

参考資料

https://vuetifyjs.com/en/api/v-overlay/#props-persistent
https://vuetifyjs.com/en/components/overlays/#usage
https://github.com/vuetifyjs/vuetify/issues/17398
https://github.com/vuetifyjs/vuetify/issues/18384

chot Inc. tech blog

Discussion