Vue.jsを使ってモーダルを作る方法

このページではJavaScriptのライブラリー「Vue.js」を使ってボタンをクリックしたらモーダルが表示されるようなプログラムの作り方を解説します。

今回の内容をマスターすれば、ちょっと今風のログインウィンドウや会員登録ウィンドウも作れるので、ぜひVue.jsを学習中の方は参考にしてみてください。

注意

今回は初心者向けの記事になっているので、コンポーネントは使いません。

今回作るもの

今回作るのは「モーダル表示ボタン」をクリックすると、モーダルが表示され、背景が薄暗くなるようなシンプルなものです。

クリックすると、モーダル が表示され、背景が薄暗くなる。

完成品はこちらに置いておきます。

Vueモーダル



まずは、画面を作成しよう

モーダル表示の処理を作る前に画面を作ります。

必要なものは以下の3つです。

  1. モーダルを表示するためのボタン
  2. 薄く黒い背景(モーダル表示時)
  3. モーダル

HTMLは次のように書きます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="dist/css/app.css">
  <title>Vueモーダル </title>
</head>
<body>
<div id="app">
<main>
  <!-- ① モーダル表示ボタン -->
  <button class="p-btn">モーダル表示ボタン</button>

  <!-- ② モーダル -->
  <div class="l-modal">
    <div class="p-modal">
      <h2 class="p-modal__title">Vueモーダル</h2> 
      <p> Hello World!</p> 

      <!-- モーダルを閉じるボタン -->
      <div class="p-modal__btn--close">×</div>
   </div> 
  </div> 

  <!-- ③ モーダル表示時の背景色(薄い黒) -->
  <div class="l-modal__bg"></div>
</main>
</div>
<script src="https://jp.vuejs.org/js/vue.js"></script>
script src="dist/js/main.js"></script>
</body>
</html>

これで画面を見てみると、下のようになります。

次にスタイルを当てていきましょう。

CSSは次のようになります。

/* ==================================
// モーダル背景(薄黒)
// ==================================*/
.l-modal__bg {
width: 100%;
height: 100%;
background: rgba(89, 89, 89, 0.6);
position: fixed;
top: 0;
left: 0;
}

/* ==================================
// モーダル
// ==================================*/
/* レイアウト */
.l-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99;
}

/* モーダルのサイズなど */
.p-modal {
width:600px;
background: #fff;
border-radius: 3px;
padding: 10px 25px;
box-sizing: border-box;
position: relative;
top: 50%;
left: 50%;
-webkit-transform : translate(-50%,-50%);
transform : translate(-50%,-50%);
}

/* モーダル内 タイトル */
.p-modal__title{
font-size: 24px;
margin-bottom: 25px;;
font-weight: bold;
}

/* モーダル閉じるボタン */
.p-modal__btn--close{
font-size: 36px;
position: absolute;
top: 0px;
right: 20px;
}

.p-modal__btn--close:hover{
cursor: pointer;
}

/* ==================================
// ボタン
// ==================================*/
.p-btn {
background: #4f9df4;
outline: none;
border: none;
display: block;
width:200px;
height:50px;
margin: 100px auto;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2), 0 2px 3px -2px rgba(0, 0, 0, 0.15);
color: #fff;
font-size: 16px;
border-radius: 7px;
transition: .5s;
}

これで、見た目が綺麗になりました。

モーダル ・モーダル背景を初回表示時は非表示にしよう

今のままだと、モーダルと背景の薄い黒が表示されている状態です。

なので、これを非表示にしましょう。

CSSの display:none で非表示にすることもできますが、せっかくVueを使うので、ここはv-ifを使ってみましょう。

v-ifは条件の結果がfalseの場合その要素が非表示になり、trueの場合は表示されるようになります。

やり方は次のようになります。

  1. モーダルとモーダル背景用のフラグ的なものを用意し、初期値をfalseにしておく
  2. v-ifでそのフラグ的なものをセットしておく

1. モーダルとモーダル背景用のフラグ的なものを用意し、初期値をfalseにしておく

jsファイルに次のように書きます。

const app = new Vue({
  el: '#app',
  data: {
    modalVisible: false, // モーダル
    modalBgVisible: false //モーダル背景色(薄黒)
  }
})

「modalVisible」と「modalBgVisible」がそのフラグ的なものです。

初期値をfalseで設定しておきます。

2. v-ifでそのフラグ的なものをセットしておく

非表示にしたいのは、「モーダル」と「モーダル背景」です。

なので、この2つにv-ifを追加します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="dist/css/app.css">
  <title>Vueモーダル </title>
</head>
<body>
<div id="app">
<main>
  <!-- ① モーダル表示ボタン -->
  <button class="p-btn">モーダル表示ボタン</button>

  <!-- ② モーダル -->
  <div v-if="modalVisible" class="l-modal">
    <div class="p-modal">
      <h2 class="p-modal__title">Vueモーダル</h2> 
      <p> Hello World!</p> 

      <!-- モーダルを閉じるボタン -->
      <div class="p-modal__btn--close">×</div>
   </div> 
  </div> 

  <!-- ③ モーダル表示時の背景色(薄い黒) -->
  <div v-if="modalBgVisible" class="l-modal__bg"></div>
</main>
</div>
<script src="https://jp.vuejs.org/js/vue.js"></script>
script src="dist/js/main.js"></script>
</body>
</html>

これで画面を見てみると、下のようにモーダルとモーダル背景が非表示になりました。




ボタンをクリックしたら、モーダルと背景が表示されるようにしよう

では、次はボタンをクリックしたらモーダルと背景が表示されるようにしましょう。

今、v-ifの条件がfalseになので、ボタンをクリックした時にtrueに変えてあげればいいですね。

やり方は次のようになります。

  1. ボタンをクリックした時のイベント(関数)を用意
  2. イベントの中で、フラグ的なものをfalseからtrueに変更する

1. ボタンをクリックした時のイベント(関数)を用意

ボタンに対して、クリックイベントを追加します。

書き方は「v-on:click=”呼び出したい関数名”」です。今回は「v-on:click=”showModal”」としました。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="dist/css/app.css">
  <title>Vueモーダル </title>
</head>
<body>
<div id="app">
<main>
  <!-- ① モーダル表示ボタン -->
  <button v-on:click="showModal" class="p-btn">モーダル表示ボタン</button>

  <!-- ② モーダル -->
  <div v-if="modalVisible" class="l-modal">
    <div class="p-modal">
      <h2 class="p-modal__title">Vueモーダル</h2> 
      <p> Hello World!</p> 

      <!-- モーダルを閉じるボタン -->
      <div class="p-modal__btn--close">×</div>
   </div> 
  </div> 

  <!-- ③ モーダル表示時の背景色(薄い黒) -->
  <div v-if="modalBgVisible" class="l-modal__bg"></div>
</main>
</div>
<script src="https://jp.vuejs.org/js/vue.js"></script>
script src="dist/js/main.js"></script>
</body>
</html>

これで、ボタンをクリックすると、showModal()が呼び出されます。

2. イベントの中で、フラグ的なものをfalseからtrueに変更する

では、showModal()の中で、フラグ的なものをfalseからtrueに変更しましょう。

const app = new Vue({
  el: '#app',
  data: {
    modalVisible: false, // モーダル
    modalBgVisible: false //モーダル背景色(薄黒)
  }
  methods: {
    showModal: function(){
      this.modalVisible = true
      this.modalBgVisible = true
    }
  }
)

これでボタンを押した時に、falseからtrueになります。

実際に画面で確認すると、ボタンをクリックした時にモーダルと背景が表示されるようになりました。

閉じるボタンをクリックした時の処理を加えよう

今のままですと、モーダルは表示できましたが、表示されたモーダルを閉じることができません。

そこで、「×」ボタンをクリックした時に、閉じる処理を加えます。

やり方は次の通り

  1. 「×」ボタンをクリックした時のイベントを用意
  2. イベントの中で、フラグ的なものをtrueからfalseに変更する

1. 「×」ボタンをクリックした時のイベントを用意

「×」ボタンに対して、クリックイベントを追加します。

今回は「v-on:click=”closeModal”」としました。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="dist/css/app.css">
  <title>Vueモーダル </title>
</head>
<body>
<div id="app">
<main>
  <!-- ① モーダル表示ボタン -->
  <button v-on:click="showModal" class="p-btn">モーダル表示ボタン</button>

  <!-- ② モーダル -->
  <div v-if="modalVisible" class="l-modal">
    <div class="p-modal">
      <h2 class="p-modal__title">Vueモーダル</h2> 
      <p> Hello World!</p> 

      <!-- モーダルを閉じるボタン -->
      <div v-on:click="closeModal" class="p-modal__btn--close">×</div>
   </div> 
  </div> 

  <!-- ③ モーダル表示時の背景色(薄い黒) -->
  <div v-if="modalBgVisible" class="l-modal__bg"></div>
</main>
</div>
<script src="https://jp.vuejs.org/js/vue.js"></script>
script src="dist/js/main.js"></script>
</body>
</html>

これで、「×」ボタンをクリックすると、closeModal()が呼び出されます。

2. イベントの中で、フラグ的なものをtrueからfalseに変更する

では、closeModal()の中で、フラグ的なものをfalseからtrueに変更しましょう。

const app = new Vue({
  el: '#app',
  data: {
    modalVisible: false, // モーダル
    modalBgVisible: false //モーダル背景色(薄黒)
  }
  methods: {
    showModal: function(){
      this.modalVisible = true
      this.modalBgVisible = true
    },
    closeModal: function(){
      this.modalVisible = false
      this.modalBgVisible = false
    }
  }
)

これで「×」ボタンを押した時に、trueからfalseになります。


背景をクリックした時もモーダルを閉じるようにしよう(応用)

一応、ここまででモーダルの表示・非表示ができるようになりましたが、今のままですと、「×」ボタンを押さなければモーダルが閉じません。

利便性を高めるためにも、背景をクリックした時も同様にモーダルを閉じるようにしましょう。

やり方ですが、モーダル背景に「v-on:click=”closeModal”を追加する」ではありません。試しにやってもらうとわかると思いますが、背景をクリックしても何も反応しないでしょう。

 

理由はCSSを見て、今回の構成を考えてもらうとわかると思いますが、下のイラストのようにモーダル背景の上に透明のシート(クラス名:l-modal)が被さっている状態で、その中心にモーダル(クラス名:p-modal)が置かれているためです。

つまり、あなたがクリックしているのは、モーダル背景ではなく、「l-modal」ということになります。

なので、このl-modalに対して、「v-on:click=”closeModal”を追加する」が正解です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="dist/css/app.css">
  <title>Vueモーダル </title>
</head>
<body>
<div id="app">
<main>
  <!-- ① モーダル表示ボタン -->
  <button v-on:click="showModal" class="p-btn">モーダル表示ボタン</button>

  <!-- ② モーダル -->
  <div v-if="modalVisible" v-on:click="closeModal"  class="l-modal">
    <div class="p-modal">
      <h2 class="p-modal__title">Vueモーダル</h2> 
      <p> Hello World!</p> 

      <!-- モーダルを閉じるボタン -->
      <div v-on:click="closeModal" class="p-modal__btn--close">×</div>
   </div> 
  </div> 

  <!-- ③ モーダル表示時の背景色(薄い黒) -->
  <div v-if="modalBgVisible" class="l-modal__bg"></div>
</main>
</div>
<script src="https://jp.vuejs.org/js/vue.js"></script>
script src="dist/js/main.js"></script>
</body>
</html>

これで、背景をクリックした時にも、モーダルが閉じるようになります。

が、まだ問題があります。

ややこしいですね。。。

しかし、今のままだと、モーダルのどこをクリックしてもモーダルが閉じるようになっています。

じゃあ、z-indexでl-modalより大きい数値を指定すれば?

と思ったあなた。

それは無理です。

そもそもl-modalはp-modalの親要素なので、l-modalより大きい値のz-indexを指定しても、効果がありません。

では、どうするかというと、p-modal内がクリックされても、イベント(フラグの true → false処理 )が発生しないようにします。

どうするかというと次の通り。

  1. p-modalにクリックイベントを追加
  2. イベント内で処理をキャンセルする。

1. p-modalにクリックイベントを追加

p-modalに対して、クリックイベントを追加します。

今回は「v-on:click=”cancelEvent”」としました。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="dist/css/app.css">
  <title>Vueモーダル </title>
</head>
<body>
<div id="app">
<main>
  <!-- ① モーダル表示ボタン -->
  <button v-on:click="showModal" class="p-btn">モーダル表示ボタン</button>

  <!-- ② モーダル -->
  <div v-if="modalVisible" class="l-modal">
    <div v-on:click="cancelEvent" class="p-modal">
      <h2 class="p-modal__title">Vueモーダル</h2> 
      <p> Hello World!</p> 

      <!-- モーダルを閉じるボタン -->
      <div v-on:click="closeModal" class="p-modal__btn--close">×</div>
   </div> 
  </div> 

  <!-- ③ モーダル表示時の背景色(薄い黒) -->
  <div v-if="modalBgVisible" class="l-modal__bg"></div>
</main>
</div>
<script src="https://jp.vuejs.org/js/vue.js"></script>
script src="dist/js/main.js"></script>
</body>
</html>

これで、p-modal内をクリックすると、cancelEvent()が呼び出されます。

イベント内で処理をキャンセルする

イベントとキャンセルしたい場合は、stopPropagation()メソッドを使います。

書き方は次の通り。

const app = new Vue({
  el: '#app',
  data: {
    modalVisible: false, // モーダル
    modalBgVisible: false //モーダル背景色(薄黒)
  }
  methods: {
    showModal: function(){
      this.modalVisible = true
      this.modalBgVisible = true
    },
    closeModal: function(){
      this.modalVisible = false
      this.modalBgVisible = false
    },
    cancelEvent: function(){ 
     event.stopPropagation() 
   }
  }
)

これでp-modal内をクリックされても、フラグの値変更が行われなくなります。

以上で完成です!

あとはアニメーションをつけたり、スタイルを調整すると完成ページと同じようなものが作れます。

Vueモーダル

Vueを勉強されている方の参考になれば幸いです。

Vueの学習におすすめの書籍

created by Rinker
¥4,555 (2022/12/05 22:31:30時点 Amazon調べ-詳細)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA