コンポーネントとは?
コンポーネントとは、そのままの意味としては、
部品とか、構成要素とかといったものがあります。
Vue.jsにおけるコンポーネントという概念も、
大まかにはそのような意味で、
より具体的に言うと、
ボタンとか、ヘッダーとか、Webページの構成要素を指しています。
具体例を出します。
<script setup lang="ts">
import { ref } from 'vue'
import Aim from './Aim.vue'
const isShow = ref(true)
const change = () => {
if (isShow.value) {
isShow.value = false
} else {
isShow.value = true
}
}
</script>
<template>
<Aim v-if="isShow" />
<button @click="change" class="rounded-lg m-2 p-2 border border-gray-300 bg-gray-100">isShow</button>
</template>
たとえば、このコードの場合、
Aim.vueというコンポーネントをimportして、
使用しています。
左側のテストと言う部分が、
Aimコンポーネントです。
このように、Webページの構成要素となるものを、
コンポーネントといいます。
通常、コンポーネントは.vueファイルに定義され、
親(コンポーネントを使用する側)でimportをします。
なぜコンポーネントとして切り出すのかというと、
再利用性を高めて、コードの保守性や見通しを良くするためです。
例えば、同じようなボタンが何度も記述されていては、
冗長なので、ボタンのコンポーネントを.vueファイルに定義して、
何度も使い回せるようにするという感じです。
ちなみに、.vueファイルにコンポーネントを定義することを、
単一ファイルコンポーネント(SFC)と言うらしいです。
https://ja.vuejs.org/guide/essentials/component-basics.html
コンポネント間通信
コンポネントのメリットは、これだけではなく、
それぞれが独立していて、親から子へのデータの受け渡し、
通信をすることもできる点があります。
この子から親、親から子のデータの受け渡しの方法として、
Vue.jsには、propsとemitというものがあります。
以下、この2つについて解説します。
props
propsとは、親コンポーネントから子コンポーネントにデータを
渡す仕組みのことです。
props自体は、Vue.js独自の概念ではなく、
Reactとかにも存在します。
具体例として、子コンポーネントとして、
Child.vueを作成してみます。
<template>
<div>
<p>Prop A: {{ propA }}</p>
<p>Prop B: {{ propB }}</p>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
propA: {
type: String,
required: true
},
propB: {
type: Number,
default: 100
}
})
</script>
Vue3のComposition APIでは、
definePropsという関数を使ってpropsを定義します。
上記の場合、propAとpropBという2つのpropsが定義されています。
これを親から呼び出す場合は、
<script setup lang="ts">
import { ref } from 'vue'
import Aim from './Aim.vue'
import Child from './Child.vue'
const isShow = ref(true)
const change = () => {
if (isShow.value) {
isShow.value = false
} else {
isShow.value = true
}
}
</script>
<template>
<Aim v-if="isShow" />
<Child
prop-a="hello world"
prop-b="399"
/>
<button @click="change" class="rounded-lg m-2 p-2 border border-gray-300 bg-gray-100">isShow</button>
</template>
先程の、TheWelcom.vueに追記しました。
Aimコンポーネントと同様に、Childコンポーネントもインポートしています。
その際、prop-aという感じで、
definePropsで定義されているpropsを渡しています。
この場合、hello worldという文字列をChildコンポーネントに渡しています。
変数をpropsにわたす場合は、
prop-a="hello world"の部分を
<Child
:prop-a="greeet"
prop-b="399"
/>
というように、
v-bindを使用すると渡すことができます。
v-bindとはなんぞや?って言う人は、
こちらの記事で解説しているので、
詳細はこちらを御覧ください。
-
参考【Vue3/v-model】双方向データバインディングとは?
Vue.jsの概念に、双方向データバインディングというものがあります。 これは、単方向データバインディングに対するものです。 本記事では、双方向データバインディングの解説を通して、単方向データバインデ ...
続きを見る
emit
次にemitです。
propsが親から子へのデータの流れに対して、
emitは、その反対の子から親へのデータの流れに対応します。
<!-- 親 -->
<script setup lang="ts">
import { ref } from 'vue'
import Child from './Child.vue'
const greet = 'hello gwge'
const print = ():void => {
console.log('emit')
}
</script>
<template>
<Child
:prop-a="greet"
prop-b="399"
@submit="print"
/>
</template>
<!-- 子 -->
<template>
<div>
<p>Prop A: {{ propA }}</p>
<p>Prop B: {{ propB }}</p>
</div>
<button @click="submit">Submit</button>
</template>
<script setup lang="ts">
const props = defineProps({
propA: {
type: String,
required: true
},
propB: {
type: Number,
default: 100
}
})
const emit = defineEmits(["submit"])
const submit = () => {
emit("submit")
}
</script>
emitは、Vue3 Composition APIの場合、
子の方に、defineEmitsという形で定義し、
emit("submit")で親のv-onディレクティブのsubmitを探しにいき、
そこのメソッドを実行し、printメソッドが走っているという流れです。
propsのときと同じく、
defineEmitsなどは、基本的に子の方で定義します。
emitは、Reactなどには存在せず、
Vue.js独特の機能です。
Vue.jsは双方向データバインディングを特徴に持つため、
このようなpropsとemitという2つのパターンがあります。
チームやPJの方針にもよりますが、
無思考でpropsやemitをたくさん書いてしまうと、
データの流れがカオスになるので、
「こういうときはprops、こういうときはemit」という風に、
大まかな方針を決めておくのがいいかなと思います。