Vue.jsでモーダルコンポーネントを作成する

この記事では、アニメーション化されたトランジションとスロットを使用して、Vue.jsで再利用可能なモーダルウィンドウコンポーネントを作成する方法を学びます。



パターン構造の定義



テンプレートを定義することから始めましょう。 背景(影)のdiv 、モーダルウィンドウ自体のdiv 、およびその構造を決定するいくつかの要素が必要です。



<template> <div class="modal-backdrop"> <div class="modal"> <slot name="header"> </slot> <slot name="body"> </slot> <slot name="footer"> </slot> </div> </div> </template>
      
      





スロットの使用に注意してください? 小道具を使用してヘッダー、ボディ、フッターを作成できますが、スロットを使用すると柔軟性が高まります。



スロットを使用すると、コンポーネントのさまざまな種類のボディコンテンツで同じモーダルウィンドウを簡単に使用できます。 モーダルウィンドウを使用してプレーンテキストを表示できますが、同じモーダルウィンドウを再利用してフォームを表示し、リクエストを送信することができます。 通常、コンポーネントを作成するには入力パラメーター(小道具)で十分ですが、入力パラメーターを介してHTMLを提供するには、レンダリングのためにv-htmlディレクティブを使用してHTMLを使用する必要があります。



ここでは、名前付きスロットを使用します。これにより、1つのコンポーネントで複数のスロットを使用できます。



名前付きスロットを定義すると、元のスロットの代わりにこの名前で識別するすべてのものが表示されます。このソーススロットを入力のプレースホルダーとしてデフォルト値と呼びます。



プレースホルダーと同様に、スロットにはデフォルトのコンテンツが含まれている場合がありますが、これを指定しないと表示されます。



提供されたコンテンツは‹slot›タグを完全に置き換えるため、ヘッダー、ボディ、およびフッターセクションに必要なクラスがあることを確認するには、対応する要素の各スロットを必要なクラスでラップする必要があります。



すべてのスロットを基本的なモーダルウィンドウのように見せるために、スロット、それらのラッパー要素、および初期CSSのいくつかのデフォルト値を設定しましょう。



 <script> export default { name: 'modal', methods: { close() { this.$emit('close'); }, }, }; </script> <template> <div class="modal-backdrop"> <div class="modal"> <header class="modal-header"> <slot name="header"> This is the default tile! <button type="button" class="btn-close" @click="close" > x </button> </slot> </header> <section class="modal-body"> <slot name="body"> I'm the default body! </slot> </section> <footer class="modal-footer"> <slot name="footer"> I'm the default footer! <button type="button" class="btn-green" @click="close" > Close me! </button> </slot> </footer> </div> </div> </template> <style> .modal-backdrop { position: fixed; top: 0; bottom: 0; left: 0; right: 0; background-color: rgba(0, 0, 0, 0.3); display: flex; justify-content: center; align-items: center; } .modal { background: #FFFFFF; box-shadow: 2px 2px 20px 1px; overflow-x: auto; display: flex; flex-direction: column; } .modal-header, .modal-footer { padding: 15px; display: flex; } .modal-header { border-bottom: 1px solid #eeeeee; color: #4AAE9B; justify-content: space-between; } .modal-footer { border-top: 1px solid #eeeeee; justify-content: flex-end; } .modal-body { position: relative; padding: 20px 10px; } .btn-close { border: none; font-size: 20px; padding: 20px; cursor: pointer; font-weight: bold; color: #4AAE9B; background: transparent; } .btn-green { color: white; background: #4AAE9B; border: 1px solid #4AAE9B; border-radius: 2px; } </style>
      
      





そして、モーダルウィンドウコンポーネントの非常にシンプルなバージョンを作成しました!



アニメーション化されたトランジションを追加する



モーダルウィンドウが突然開くことに注意してください。 アニメーション化されたトランジションを使用して、ウィンドウの入力/出力をよりスムーズにすることができます。



Vueはラッパーコンポーネント‹transition›を提供します。これにより、HTML要素またはVueコンポーネントの表示と非表示のアニメーション化されたトランジションを追加し、CSSクラスとJavaScriptフックの両方を使用できます。



‹transition›要素にラップされたコンポーネントまたは要素が挿入または削除されるたびに、Vueは要素にCSS遷移があるかどうかを確認し、適切なタイミングでそれらを追加または削除します。 JavaScriptフックについても同じことが言えますが、今回のケースではCSSのみを使用します。



アイテムが追加または削除されると、 6つのクラスがI / Oトランジションに適用されます。 それらのそれぞれには、遷移名の接頭辞があります。 このガイドでは、移行がどのように機能するかについての詳細な説明があります。



まず、モーダルウィンドウに‹transition›要素を追加します。



 <template> <transition name="modal-fade"> <div class="modal-backdrop"> <div class="modal"> ... </div> </div> </transition> </template>
      
      





次に、CSSクラスを追加して、透明度を変更します-ウィンドウをスムーズに表示/非表示にするために:



 <style> .modal-fade-enter, .modal-fade-leave-active { opacity: 0; } .modal-fade-enter-active, .modal-fade-leave-active { transition: opacity .5s ease } </style>
      
      





これでモーダルウィンドウコンポーネントがスムーズに開閉します!



モーダルウィンドウをよりアクセスしやすくする



不足している唯一のことは、障害のある人にとってコンポーネントをよりアクセシブルにすることです。



これは、 aria属性を使用して実現できます。



role = "dialog"を追加すると、サポートソフトウェアがコンポーネントを、他のユーザーインターフェイスとは別のダイアログ(モーダル)アプリケーションウィンドウとして識別するのに役立ちます。 対話の役割を追加することは便利ですが、それをアクセス可能にするだけでは不十分です。それに応じてマークする必要があります。 これは、 aria-labelledbyおよびaria-describedb y属性を通じて実現できます。 また、閉じるボタンにも注意してください。



モーダルコンポーネントの最終バージョンは次のようになります。



 <script> export default { name: 'modal', methods: { close() { this.$emit('close'); }, }, }; </script> <template> <transition name="modal-fade"> <div class="modal-backdrop"> <div class="modal" role="dialog" aria-labelledby="modalTitle" aria-describedby="modalDescription" > <header class="modal-header" id="modalTitle" > <slot name="header"> This is the default tile! <button type="button" class="btn-close" @click="close" aria-label="Close modal" > x </button> </slot> </header> <section class="modal-body" id="modalDescription" > <slot name="body"> I'm the default body! </slot> </section> <footer class="modal-footer"> <slot name="footer"> I'm the default footer! <button type="button" class="btn-green" @click="close" aria-label="Close modal" > Close me! </button> </slot> </footer> </div> </div> </transition> </template> <style> .modal-backdrop { position: fixed; top: 0; bottom: 0; left: 0; right: 0; background-color: rgba(0, 0, 0, 0.3); display: flex; justify-content: center; align-items: center; } .modal { background: #FFFFFF; box-shadow: 2px 2px 20px 1px; overflow-x: auto; display: flex; flex-direction: column; } .modal-header, .modal-footer { padding: 15px; display: flex; } .modal-header { border-bottom: 1px solid #eeeeee; color: #4AAE9B; justify-content: space-between; } .modal-footer { border-top: 1px solid #eeeeee; justify-content: flex-end; } .modal-body { position: relative; padding: 20px 10px; } .btn-close { border: none; font-size: 20px; padding: 20px; cursor: pointer; font-weight: bold; color: #4AAE9B; background: transparent; } .btn-green { color: white; background: #4AAE9B; border: 1px solid #4AAE9B; border-radius: 2px; } </style>
      
      





アプリケーションでモーダルウィンドウコンポーネントを使用する



これで、アプリケーションにコンポーネントを含めることでコンポーネントを使用できます。 ここで動作するコンポーネント-codepenを試すこともできます。



 <script> import modal from './components/modal.vue'; export default { name: 'app', components: { modal, }, data () { return { isModalVisible: false, }; }, methods: { showModal() { this.isModalVisible = true; }, closeModal() { this.isModalVisible = false; } }, }; </script> <template> <div id="app"> <button type="button" class="btn" @click="showModal" > Open Modal! </button> <modal v-show="isModalVisible" @close="closeModal" /> </div> </template>
      
      







PSこの記事はこの外国語の翻訳です。 以下のコメントで、それがどのように起こったかを説明しました。

PSS記事の翻訳を人道的なものにしました。



All Articles