
vue.js入門!エンジニアが解説するcomponent基礎
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(単方向バインディング(子 → 親))
を組み合わせる方法です。
以下のコードの概要です。
- 親で子で表示する文字列を設定(string)
- 子でクリックすると親にクリックイベントを送る(モジと書かれたデータを送信)
- 親で文字列がstring → モジに変更
- 子の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を同期処理に変換します。
以下のコードの先程と同じような処理を行っています。
- 親で子で表示する文字列を設定(string)
- 子でクリックすると親にクリックイベントを送る(モジと書かれたデータを送信)
- 親で文字列がstring → モジに変更
- 子の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を紹介しました。
とても重要な機能なので、何回も読み直してマネぶことをオススメします。