はじめに
Webアプリを開発する際、モーダルを使用してユーザーに追加情報を提供したり、フォーム入力を促したりすることがよくあります。
本記事では、Vue 3 の shallowRef
や ref
を使って 動的にコンポーネントを切り替えるモーダル の実装方法を紹介します。
「ボタンをクリックすると、指定したコンポーネントがモーダル内に表示される」という動作を実現していきます。
実装の概要
今回の実装では、以下の3つのコンポーネントを作成し、以下の流れでモーダルを動的に表示します。
MainComponent.vue
(モーダルを開くボタンを持つコンポーネント)
SlideupModal.vue
(モーダルコンポーネント)
ModalComponent.vue
(モーダルで表示するコンポーネント)
流れ
- ボタンをクリック →
callModal
メソッドを実行。 - モーダルに表示するコンポーネントを指定 →
childComponent
にセット。 - モーダルのタイトルや props を設定。
- モーダルを開く。
1. モーダルを開く親コンポーネントを実装 (MainComponent.vue)
このコンポーネントには、モーダルを開くためのボタンがあり、クリックすると SlideupModal.vue
に ModalComponent.vue
を渡します。
実装例:
<template>
<button
@click=“callModal(‘modalComponent’, ‘モーダル‘, modalComponentProps)”
>
モーダルを開く
</button>
<SlideupModal
:childComponent=“childComponent”
:childProps=“childProps”
:headingText=“headingText”
:calledElement=“calledElement”
ref=“slideupModal”
/>
</template>
<script setup>
import SlideupModal from ‘@/components/SlideupModal.vue’;
import ModalComponent from ‘@/components/ModalComponent.vue’;
import { shallowRef, ref, computed } from ‘vue’;
const modalInfo = computed(() => state.modalInfo);
const componentsOnModal = shallowRef({
modalComponent: ModalComponent
});
const childComponent = shallowRef(null);
const childProps = ref({});
const headingText = ref(‘’);
const slideupModal = ref(null);
const calledElement = ref(null);
const callModal = (componentName, headingTitle, event) => {
childComponent.value = componentsOnModal.value[componentName];
childProps.value = { modalInfo: modalInfo.value };
headingText.value = headingTitle;
calledElement.value = event.currentTarget;
slideupModal.value.openModal();
};
</script>
この実装のポイント:
・SlideupModal
は下部にポップアップ表示されるモーダル(slide-up modal) コンポーネント。
・shallowRef
を使い、モーダルで表示するコンポーネントを動的に変更。
・componentsOnModal
にモーダルで表示するコンポーネントを定義。
childComponent.value = componentsOnModal.value[componentName]
→ ロードするコンポーネントを指定する (ModalComponent
)。
childProps.value = { modalInfo: modalInfo.value }
→ modalInfo
データを渡す
headingText.value = headingTitle
→ モーダルのタイトルを設定。
・callModal
メソッドで コンポーネント名(modalComponent
)・タイトル(モーダル
)・props(modalComponentProps
) をセット。
・slideupModal.value.openModal()
で モーダルを開く。
2. モーダルの基本コンポーネントを作成 (SlideupModal.vue)
まず、モーダルの共通コンポーネント SlideupModal.vue
を作成します。
このコンポーネントは、childComponent
という動的なコンポーネントを受け取り、モーダル内にレンダリングする仕組みになっています。
モーダル自体はシンプルにし、<component :is=“childComponent” />
を使って動的にコンポーネントを切り替えます。
<template>
<div :class=“{ view: isView }” @click=“closeModal()“></div>
<div :class=“{ view: isView }” ref=“modalContent”>
<header>
<h2>{{ headingText }}</h2>
<button @click=“closeModal()“>×</button>
</header>
<div>
<component :is=“childComponent” v-bind=“childProps || {}“></component>
</div>
</div>
</template>
<script setup>
import { ref } from ‘vue’;
const isView = ref(false);
const headingText = defineProps([‘headingText’]);
const childComponent = defineProps([‘childComponent’]);
const childProps = defineProps([‘childProps’]);
const openModal = () => {
isView.value = true;
};
const closeModal = () => {
isView.value = false;
};
</script>
この実装のポイント:
・isView
モーダルの表示/非表示状態を制御する。
・:is=“childComponent”
で 動的にコンポーネントを切り替え。
・openModal()
と closeModal()
で モーダルの表示/非表示を制御。
3. モーダルで表示するコンポーネントを作成(ModalComponent.vue)
モーダル内で表示する ModalComponent.vue
を作成します。
4. 動作確認
・ボタンをクリックすると ModalComponent.vue
がモーダル内に表示される。
・背景や閉じるボタンを押すとモーダルが閉じる。
・他のコンポーネントにも応用可能。
5. まとめ
この方法を使うことで、複数の異なるコンポーネントを動的に切り替えてモーダル内に表示できます。
shallowRef
を活用して 動的にコンポーネントを切り替え
v-bind
を使って props を渡す
汎用的なモーダル を実装可能
モーダルの再利用性を高めたい方は、ぜひ試してみてください!