コンポーネントを深く理解する(前半)
シングルファイルコンポーネント(SFC)
Vue.jsのシングルファイルコンポーネント(SFC)は、.vue
拡張子を持つファイル内にHTML、JavaScript、CSSを一つのファイルにまとめることができる強力な機能です。SFCを使用することで、コンポーネントの構造が明確になり、開発の効率が向上します。以下に、SFCの構成と具体的な使用例を示します。
SFCの基本構造
一般的なSFCは以下の3つのセクションから構成されます。
<template>
: コンポーネントのHTMLマークアップを含みます。<script>
: コンポーネントのJavaScriptロジックを含みます。Vue 3では<script setup>
構文も利用できます。<style>
: コンポーネント専用のスタイルを定義します。スコープ付きCSSも利用可能です。
具体的な例
基本的なSFC
<template>
<div class="my-component">
{{ message }}
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello, Vue SFC!'
}
}
}
</script>
<style scoped>
.my-component {
color: blue;
font-size: 20px;
}
</style>
このコンポーネントは、青色で20pxのフォントサイズのテキストを表示します。scoped
属性があるため、スタイルはこのコンポーネントに限定されます。
<script setup>
を使用したSFC
Vue 3で導入された<script setup>
構文を使用すると、より宣言的かつ簡潔にコンポーネントを定義できます。
<template>
<div>{{ greeting }}</div>
</template>
<script setup>
import { ref } from 'vue'
const greeting = ref('Hello, Vue 3 with <script setup>!')
</script>
<style>
div {
color: red;
}
</style>
この例では、ref
を使用してリアクティブなデータgreeting
を定義しています。テンプレート内でこのデータを使用することで、テキストを表示しています。
SFCの利点
- モジュール性: HTML、JavaScript、CSSが1つのファイル内に集約されているため、コンポーネントごとにファイルを分けることができ、プロジェクトの構造が明確になります。
- スコープ付きスタイル:
<style scoped>
を使用することで、スタイルをコンポーネント内に限定でき、スタイルの衝突を避けられます。 - 再利用可能: コンポーネントを再利用しやすくなり、大規模なアプリケーションの開発が効率的になります。
- 開発ツールのサポート: Vue CLIやViteなどのツールはSFCをフルサポートしており、ホットリロードやコード分割などの機能を簡単に利用できます。
setup関数の使用
Vue 3の導入により、Composition APIが新たに追加され、その中心的な機能の一つがsetup
関数です。setup
関数は、コンポーネントのロジックとリアクティブなデータをより柔軟に扱うための新しいオプションです。この関数は、コンポーネントのライフサイクルの初期段階で実行され、props
やcontext
にアクセスすることができます。
setup
関数の使用前
Vue 2では、コンポーネントのデータ、メソッド、ライフサイクルフック、ウォッチャなどは、コンポーネントオブジェクトのオプションとして定義されました。
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
},
mounted() {
console.log('コンポーネントがマウントされました。');
}
}
この方法では、関連するロジックがコンポーネント内で分散されがちであり、大規模なコンポーネントでは管理が難しくなることがありました。
setup
関数の導入後
Vue 3では、setup
関数を使用して、コンポーネントのロジックをより構造化し、関連する機能をまとめて定義できます。これにより、コードの可読性と再利用性が向上します。
import { ref, onMounted } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => {
count.value++
}
onMounted(() => {
console.log('コンポーネントがマウントされました。');
})
return { count, increment }
}
}
setup
関数内で使用されるref
はリアクティブなデータを作成し、onMounted
はコンポーネントがマウントされた後に実行されるべき処理を定義します。setup
関数から返された値は、テンプレート内で直接使用できます。
setup
関数の機能
- リアクティブな参照:
ref
とreactive
を使用して、リアクティブなデータを定義できます。 - コンポーネントプロパティ:
props
とcontext
を通じて、親コンポーネントからのプロパティやスロットにアクセスできます。 - ライフサイクルフック:
onMounted
、onUpdated
などのライフサイクルフックを使用できます。 - ウォッチャ:
watch
やwatchEffect
を使用して、リアクティブなデータの変更を監視できます。 - 提供/注入:
provide
とinject
を使用して、コンポーネントツリー間でのデータの提供と注入が可能です。
変化
setup
関数の導入により、Vueコンポーネントの定義方法が大きく変化しました。従来のオプションAPIでは、コンポーネントのオプションごとにロジックが分散していましたが、Composition API(とその中心であるsetup
関数)により、関連する機能をまとめて記述できるようになり、コンポーネントの可読性と再利用性が向上しました。また、大規模なアプリケーションや複雑なコンポーネントの開発において、より柔軟かつ効率的なコーディングが可能になりました。
コンポーネントの基礎
Vue.jsのコア機能の一つは、再利用可能なコンポーネントを作成できることです。
Vue.componentを使用してグローバルコンポーネントを定義します。 グローバルコンポーネントはカスタム要素としてtemplate内で使用できます。
Vue.component('todo-item', {
template: '<li>これはTODOアイテムです</li>'
});
ローカルで定義することもできます。
<template>
<li>これはTODOアイテムです</li>
</template>
コンポーネント間のデータの受け渡し(PropsとEvents)
Props
<script setup>
defineProps(['message'])
</script>
<template>
<span>
メッセージは {{ message }}
</span>
</template>
Emits
<script setup>
const emit = defineEmits(['increase']);
const emitIncrease = () => {
emit('increase');
}
</script>
<template>
<button @click="emitIncrease">クリックしてカウントアップ</button>
</template>
スロットを使ったコンテンツ配信
匿名スロット
コンポーネント内の未指定のコンテンツを受け入れます。
<template>
<div>
<slot>デフォルトコンテンツ</slot>
</div>
</template>
名前付きスロット
特定のスロットにコンテンツを挿入するために名前を使用します。
<template>
<div>
<slot>デフォルトコンテンツ</slot>
<slot name="header">Header</slot>
<slot name="footer">Footer</slot>
</div>
</template>
ダイナミックコンポーネントと非同期コンポーネント
ダイナミックコンポーネント
is
属性を使用して、動的にコンポーネントを切り替えることができます。
<template>
<div>MyComponent</div>
</template>
非同期コンポーネント
コンポーネントを非同期にロードすることで、初期ロード時のパフォーマンスを向上させることができます。
<template>
<div>私は非同期でロードされました!</div>
</template>