モーダル機能と学ぶ(transition,props,emit)

Vueの4つの特徴(コンポーネントトランジション、拡張性、リアクティブネス)の一つで

あるトランジションについて、モーダルの実装を通して学習していきたいと思う。

transitionって何?

Vue は、transition ラッパーコンポーネントを提供しています。このコンポーネントは、次のコンテキストにある要素やコンポーネントに entering/leaving トランジションを追加することを可能にします:

動きをつけたい箇所をtransitionで囲むってことなのかな?

そんでもって、動きをつけるかどうかは、v-ifを使って表すこともあるらしい。

v-ifに関して、

trueの時は、cssで定義したenter-active・leave-active、

falseの時はleave-to・enter

になる。

では、モーダルを使って考えてみる。

Enter/Leave とトランジション一覧 - Vue.js

どうやって使うの?

index.html

<div id="demo">
  <button v-on:click="show = !show">
    Toggle
  </button>
  <transition name="fade">
    <p v-if="show">hello</p>
  </transition>
</div>

v-on:clickで、showと!showの切り替えを行なっている。

v-onを使うとイベントハンドリングができるらしい。

つまり、Toggleをclickすると、showと!showの切り替えが行われるということになる。

ほんでもって、transition内にイベントの対象を記述している。

もしshowの場合、helloはデフォルトの状態のままで、!showだとcssのfade-enter-to

,fade-leave-toが適用される。(cssの内容に関しては後述する)

 #main.js
new Vue({
  el: '#demo',
  data: {
    show: true
  }
})

今回は、v-if = showがtrueだからhelloがデフォルトで表示されていることを指している。

デフォルトでは、showがtrueになっている。

stylesheet.css

.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}

この、enterやleaveというのは、トランジションクラスというらしい。

下記に引用文献を貼っておく。

これらは、enter/leave トランジションのために適用される 6 つのクラスです。

  1. v-enter: enter の開始状態。要素が挿入される前に適用され、要素が挿入された 1 フレーム後に削除されます。
  2. v-enter-active: enter の活性状態。トランジションに入るフェーズ中に適用されます。要素が挿入される前に追加され、トランジション/アニメーションが終了すると削除されます。このクラスは、トランジションの開始に対して、期間、遅延、およびイージングカーブを定義するために使用できます。
  3. v-enter-toバージョン 2.1.8 以降でのみ利用可能です。 enter の終了状態。要素が挿入された 1 フレーム後に追加され (同時に v-enter が削除されます)、トランジション/アニメーションが終了すると削除されます。
  4. v-leave: leave の開始状態。トランジションの終了がトリガされるとき、直ちに追加され、1フレーム後に削除されます。
  5. v-leave-active: leave の活性状態。トランジションが終わるフェーズ中に適用されます。leave トランジションがトリガされるとき、直ちに追加され、トランジション/アニメーションが終了すると削除されます。このクラスは、トランジションの終了に対して、期間、遅延、およびイージングカーブを定義するために使用できます。
  6. v-leave-toバージョン 2.1.8 以降でのみ利用可能です。 leave の終了状態。leave トランジションがトリガされた 1 フレーム後に追加され (同時に v-leave が削除されます)、トランジション/アニメーションが終了すると削除されます。

vに、transition name="〇〇"の〇〇部分を入れた状態で使用するみたいだ。

今回の例だと、fadeを入れているから、fade-enterやfade-leave-toと表している。

成果物

Image from Gyazo

props

コンポーネントから子コンポーネントに値を渡したい時に使う

props

  • 型: Array<string> | Object

  • 詳細:

    コンポーネントからデータを受け取るためにエクスポートされた属性のリスト/ハッシュです。シンプルな配列ベースの構文、そして型チェック、カスタム検証そしてデフォルト値などの高度な構成を可能とする配列ベースの代わりとなるオブジェクトベースの構文があります。

親⇨子

使用例

// シンプルな構文
Vue.component('props-demo-simple', {
  props: ['size', 'myMessage']
})

// バリデーション付きのオブジェクト構文
Vue.component('props-demo-advanced', {
  props: {
    // 単なる型チェック
    height: Number,
    // 型チェックとその他のバリデーション
    age: {
      type: Number,
      default: 0,
      required: true,
      validator: function (value) {
        return value >= 0
      }
    }
  }
})

v-for

繰り返し処理を記載する。

idがblog-post-demo

Postテーブルのデータで、idが1~3の各タイトル表示させたい。

その場合、script内に下記記述をする。

new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue' },
      { id: 2, title: 'Blogging with Vue' },
      { id: 3, title: 'Why Vue is so fun' }
    ]
  }
})

template内に下記記述をする。


<div id="blog-post-demo">
	<blog-post
	  v-for="post in posts"
	  v-bind:key="post.id"
	  v-bind:title="post.title"
	></blog-post>
</div>

すると、下記のようなアウトプットが得られる

My journey with Vue
Blogging with Vue
Why Vue is so fun

コンポーネントの基本 - Vue.js

プロパティ - Vue.js

emitって何?

コンポーネントの動きを親コンポーネントが察知するためのメソッド。

子⇨親

vm.$emit( eventName, […args] )

  • 引数:

    • {string} eventName
    • [...args]
  • 使用方法:

    現在の vm 上のカスタムイベントを監視します。イベントは vm.$emit によってトリガすることができます。それらのイベントトリガを行うメソッドに渡した追加の引数は、コールバックがすべて受け取ります。

  • 例:

    vm.$on('test', function (msg) {
      console.log(msg)
    })
    vm.$emit('test', 'hi')
    // => "hi"
    

$emitと$onはセットで使用する。

イベントと$emitを一緒に使うこともできる

$emit をイベント名のみと共に使う場合:

Vue.component('welcome-button', {
  template: `
    <button v-on:click="$emit('welcome')">
      Click me to be welcomed
    </button>
  `
})

welcome-buttonというコンポーネントを作った。template:以下を保持している。その保持している部品の中には、クリックされるとwelcomeを発火するbuttonが格納されている。

<div id="emit-example-simple">
  <welcome-button v-on:welcome="sayHi"></welcome-button>
</div>

HTMLにemit-example-simpleというタグをつけたdivをかく。

importしたwelcome-buttonコンポーネントにクリックするとwelcomeが実行されるメソッドをかく。

new Vue({
  el: '#emit-example-simple',
  methods: {
    sayHi: function () {
      alert('Hi!')
    }
  }
})

Vueインスタンスの中に、sayHiファンクションを書く。

まとめ

コンポーネント分割を行う際に片方のコンポーネントがもう片方のコンポーネントを取り込み(import)する時、importする側を「親(コンポーネント)」と呼び、される側を「子(コンポーネント)」と呼びます。

(参考文献: https://recruit.cct-inc.co.jp/tecblog/vue-js/vue-emit-props/)

propsと$emitでデータを引き渡す - Qiita

API - Vue.js

カスタムイベント - Vue.js

コンポーネントの基本 - Vue.js

API - Vue.js