folder-solid
スキル
clock
2021-04-09
vue.js入門!エンジニアが解説するcomponent基礎

vue.js入門!エンジニアが解説するcomponent基礎

目次
caret-up-solid

Vue.js、JavaScriptフレームを初めて使う方に向けて今回はキモとなるComponentについて解説します

Componentの概念から説明してますので、初心者の方にも読みやすいと思います。

Componentとは?

Vue.js、AngularにはComponentという概念があります。

Componentを使用してVue.jsなどはコードの共通化を高めています。

共通化を行うとメンテナンス性の向上やコード量の削減をできます。

どんなプロジェクトでも必ずComponentは使用するので、Vue.jsを理解するのには必須です

使いまわし可能なパーツ

Componentは簡単に説明すると使いまわし可能なパーツです。

vueファイルの中で他のvueファイルを呼び出して使用することができます。

例えばボタンを使いまわし可能な状態で実装すれば、呼び出すだけで同じデザイン、同じ処理を呼び出し側で実装できます。

例:ボタン

実現したいこと:幅と高さが20pxの「ここをクリック」と表示されたボタンを使いまわしたい。

実装方法
 1. Aファイルで幅と高さが20pxの「ここをクリック」と表示されたボタンを作成。
 2. BファイルでボタンComponentを呼び出す。

結果:Bファイルでボタンが表示される。

この呼ばれた側(Aファイル)、呼び出し側(Bファイル)は親と子で呼ぶことが多いです。

以下からは

  • 呼び出し側 = 親
  • 呼ばれた側 = 子

で説明していきます。

Bindingとは?

上記の説明だとボタンの場合

  • ボタンのテキストが固定
  • クリック後の処理を子で書く必要があり

このような不満点があります。

Bindingはその不満点を解消する機能です。

Component間のデータ受け渡し機能

Bindingは簡単に説明するとComponent間のデータ受け渡し機能です。

Bindingを行うと

  • 親で子のテキストを変更可能にする
  • 子でイベントトリガーを親に引き継ぐ

などができます。

結果的に上記で起きていた不満点は、Bindingを行うと解決します。


これらのBindingは親と子の関係性が重要で

親から子、子から親の一方通行なBindingは一般的に単方向バインディング
親と子の双方向なBindingは一般的に双方向バインディング

と呼びます。

Bindingの概念が理解できないとComponentは上手く扱えないので頑張りましょう!

実際の使用例

ここからは実際にVue.jsのコードを見ながら実装方法を解説します。

vueファイルの説明は以下の記事で行っていますので、わからない方は参考にしてください。

Componentの使用

まずはベースとなるComponentの呼び出しを解説します。

上記の例のBindingをしていないボタンの実装方法です。

子でstring文字列を表示するvueファイルを作成し、親で子を読んでます。


:ChildComponent.vue

<template>
  string
</template>

子では処理不要なので、文字を書いているだけです。

:ParentComponent.vue

<template>
  <ChildComponent />
</template>

<script>
import ChildComponent from "xxxx/ChildComponent.vue";

export default {
  components: { ChildComponent },
};
</script>

親では子のvueファイル、ChildComponent.vueを使用するためにChildComponent.vueをimportします。

import後、html側で実際に使用する箇所に<ChildComponent />と記述すればOKです。

v-bind(単方向バインディング(親 → 子))

Componentの呼び出し方法がわかったので次に、親 → 子のBindingを説明します。

親で子のテキストを変更可能にするイメージです。

以下のコードは親で設定したテキストを子で表示します。

:ChildComponent.vue

<template>
  {{bindName}}
</template>

<script>
export default {
  props: ["bindName"],
};
</script>

子では親からのデータを受け取るため、propsを用意します。

受け取るデータの名前は親と子で名前を連携させる必要があります。
今回はbindNameと名付けます。

propsは配列型なので、親から受け取るデータを複数持つことも出来ます。

:ParentComponent.vue

<template>
  <ChildComponent :bindName="dataName" />
</template>

<script>
import ChildComponent from "xxxx/ChildComponent.vue";

export default {
  components: { ChildComponent },

  data() {
    return {
      dataName: 'string'
    };
  },
};
</script>

親ではhtml側で呼び出します。
呼び出す時に :bindName="dataName" と属性が設定されてます。

ここで親と子のデータをバインド、連携させてます。

  • bindNameは子のpropsで設定した名前
  • dataNameは親で扱っているデータの名前です。

これで、親 → 子のBindingは完了です。

v-on(単方向バインディング(子 → 親))

次に、子 → 親のBindingを説明します。

子で発生したイベントを親に検知、引き継ぐイメージです。

以下のコードは子のテキストをクリックすると親でイベントを検知して
親で表示されてるテキスト内容がstring → モジに変更します。

:ChildComponent.vue

<template>
  <div>
    <div @click="clickText()">
      クリックして変更
    </div>
  </div>
</template>

<script>
export default {

  methods: {
    clickText() {
      this.$emit('onName', 'モジ');
    }
  }
};
</script>

子ではクリックイベント設定します。
@clickがクリックイベント設定です。

script側では対象のFunction内でemitと記述してます。
これが、子から親にイベントを検知させる方法です。

  • 第一引数のonNameは検知させたい名前
  • 第二引数のモジは実際に送るデータ(オブジェクト型でもOKです)

これでクリックして変更をクリックすると親のonNameに伝播します。

:ParentComponent.vue

<template>
  {{dataName}}
  <ChildComponent @onName="changeName"/>
</template>

<script>
import ChildComponent from "xxxx/ChildComponent.vue";

export default {
  components: { ChildComponent },

  data() {
    return {
      dataName: 'string'
    };
  },

  methods: {
    changeName(item) {
      this.dataName = item
    }
  }
};
</script>

親では基本的にv-bind(単方向バインディング(子 → 親))と同様のことをしてます。

他の追加処理はテキストの変更処理です。
methods内のchangeName引数にemitで設定した値が梱包されてます。

これで、子 → 親のBindingは完了です。

応用編

今までは単方向バインディングのみだったので、双方向にデータを受け渡すことができません。

そこで以下からは、双方向バインディングの実装方法を解説します。

双方向バインディングが最も難しいので頑張りましょう!!

v-bindとv-on(双方向バインディング)

Vue.jsの双方向バインディングは大きく2種類方法があります。

最初に最もベーシックな方法を解説します。

上記で解説した

  • v-bind(単方向バインディング(子 → 親))
  • v-on(単方向バインディング(子 → 親))

組み合わせる方法です。

以下のコードの概要です。

  1. 親で子で表示する文字列を設定(string)
  2. 子でクリックすると親にクリックイベントを送る(モジと書かれたデータを送信)
  3. 親で文字列がstring → モジに変更
  4. 子のstringがモジに変更

先程まで子、親の順に書きましたが理解しやすさ優先で
ここからは親、子の順に書きます

:ParentComponent.vue

<template>
  <ChildComponent :bindName="dataName" @onName="changeName"/>
</template>

<script>
import ChildComponent from "xxxx/ChildComponent.vue";

export default {
  components: { ChildComponent },

  data() {
    return {
      dataName: 'string'
    };
  },

  methods: {
    changeName(item) {
      this.dataName = item
    }
  }
};
</script>

行っていることはv-bindとv-onをやっているだけです。

親はそこそこシンプルです。

:ChildComponent.vue

<template>
  <div>
    {{bindName}}
    <div @click="clickText()">
      クリックして変更
    </div>
  </div>
</template>

<script>
export default {
  props: ["bindName"],

  methods: {
    clickText() {
      this.$emit('onName', 'モジ');
    }
  }
};
</script>

子も同様にv-bindとv-onをやっているだけです。

分かりづらい人は、上で書いた順序通りに処理を追うと理解しやすいと思います

sync(双方向バインディング)

v-bindとv-onで双方向バインディングすると処理が少し複雑になります。

そこで、超応用のsyncの登場です。

syncは簡単に説明するとv-bindを同期処理に変換します。

以下のコードの先程と同じような処理を行っています。

  1. 親で子で表示する文字列を設定(string)
  2. 子でクリックすると親にクリックイベントを送る(モジと書かれたデータを送信)
  3. 親で文字列がstring → モジに変更
  4. 子のstringがモジに変更

:ParentComponent.vue

<template>
  <ChildComponent :bindName.sync="dataName" />
</template>

<script>
import ChildComponent from "xxxx/ChildComponent.vue";

export default {
  components: { ChildComponent },

  data() {
    return {
      dataName: 'string'
    };
  },
};
</script>

親の処理がスッキリしましたね。

ポイントはbindName.syncです。

syncを書くことでv-onで行っていた代入処理を省略できます。

:ChildComponent.vue

<template>
  <div>
    {{bindName}}
    <div @click="clickText()">
      クリックして変更
    </div>
  </div>
</template>

<script>
export default {
  props: ["bindName"],

  methods: {
    clickText() {
      this.$emit('update:bindName', 'モジ');
    }
  }
};
</script>

子も少し変化しています。
emitの第一引数にupdateが追加されてます。

updateを書くことで、親のsyncに通知がいく仕組みです。

v-onとsyncの違い

紹介したとおりsyncだと処理を省略してかけるので便利ですが注意点もあります。

syncは同期処理になのでフィルター処理をはさみたい時などデータを加工したい時は使用できません

双方向バインディングは以下の使い分けをオススメします。

  • vueファイル間でデータを加工するならv-bindとv-on
  • vueファイル間でデータを加工しないならsync

まとめ

今回はVue.jsのComponentとBindingを紹介しました。

とても重要な機能なので、何回も読み直してマネぶことをオススメします。

profile_icon
モレ
買ったものをレビューしたり、プログラミング・デザインの事について発信していきます。
twitter
twitter