Vue.js

【Vue3】初心者講座 Vol.2【コンポーネント】

vue3コンポーネントの基本
ニャンコ
ニャンコ

Vue3初心者講座今回はコンポーネント周りです。

Vueにおけるコンポーネントは、ユーザーインタフェースの部品ことです。
VUeはコンポーネントの集まりによって構成されます。

ワンコ
ワンコ
前回はこちら!

Vue3起動の仕組み

コンポーネント編集に入る前に、Vue3の起動の仕組みについて確認したいと思います。
まずは、Vue3プロジェクトのルートフォルダにある「index.html」を開いてみましょう。
詳しいファイル構成に関しては、前回まとめているのでそちらをご確認下さい。

index.html

「index.html」はトップページのファイルになります。ポイントは2点

  • 「id="app"」の中にVueアプリケーションが表示されます。
  • main.ts(TypeScriptでない場合は、main.js)がメイン処理ファイルです。
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
  </head>
  <body>
   <!-- id="app"の中にVueアプリケーションが表示されます -->
    <div id="app"></div>
    <!-- メイン処理ファイル読込 -->
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

main.ts(main.js)

Vueアプリケーションのメインスクリプトファイルです。
プロジェクトファイル作成時に追加したライブラリによって中身は多少異なりますが、何も追加しなければ以下の中身になっています。

main.tsファイルでは、Vueアプリ内で使用するモジュールやメインのコンポーネントファイルの読み込み、Vueアプリケーションの作成を行います。

// main.cssファイル読込
import './assets/main.css'

// createAppモジュールをインポート
import { createApp } from 'vue'

// メインコンポーネントファイル読込
import App from './App.vue'

// Vueアプリケーションを作成
// mountでindex.htmlの「id="app"」内に表示させています。
createApp(App).mount('#app')

App.vue

メインのコンポーネントファイルです。
ここに様々なコンポーネントや処理などを追加していき、アプリの画面を作成していきます。
初期状態では色々記述されてますが、Vueプロジェクト作成時の、サンプル画面(画像参照)の記述なので一部残して消して良いです

  • <script>タグ
  • <template>タグ
  • <style>タグ

上記三つのタグだけ残して削除。

Vueサンプル画面
// 以下だけ残して全部削除
<script setup lang="ts">

</script>

<template>

</template>

<style scoped>

</style>

Vueアプリケーションの流れを簡単に図で表すとこのようになります。

Vue3コンポーネントの基本

Vueコンポーネントは、先ほど少し触れましたが、3つのブロックに分かれています。
通常のWEBサイトでは、それぞれ別のファイルに分かれていますが、Vueのコンポーネントは、そのコンポートに関する記述は同じVueファイル内に記述できます。

  • スクリプトブロック:処理を記述
  • テンプレートブロック:HTMLタグを記述
  • スタイルブロック:CSSを記述

Vue3コンポーネントの作成

コンポーネントファイル作成

ためしに一つコンポーネントを作成してみましょう。
コンポーネントファイルは、components」フォルダの中に作成します。
今回は、「testItem.vue」という名前で作成しました。

「src」>「components」>「testItem.vue」

ちなみに最初から「components」フォルダに入っているファイルはサンプルなので全て消して大丈夫です。

<script setup lang="ts">

</script>

<template>
    <p class="">数字:<span>1</span></p>
</template>

<style scoped>
  p {
    display: flex;
    align-items: center;
  }

  span {
    color: red;
  }
</style>

スクリプトブロックには、特に何も記載せず、テンプレートブロックと、スタイルブロックに簡単なコードを書いているだけのコンポーネントです。

Vue3コンポーネントの読込

次は作成した「testItem.vue」コンポーネントを読み込んで画面に表示させます。
今回は直接メインコンポーネント「App.vue」に読み込みました。

<script setup lang="ts">
  // 作成した「testItem.vue」をインポート
  import testItem from '@/components/testItem.vue'
</script>

<template>
  <div>
      <!-- インポート名と同じタグを記述する -->
      <testItem/>
  </div>
</template>

ここまで記述したらターミナルで、npm run devコマンドを打ち、表示を確認します。
正しく表示されると、左のように「testItem.vue」コンポーネントに入力した内容が表示されます。

scriptブロック解説

scriptブロックでは、作成した「testItem.vue」コンポーネントを読み込んでいるだけです。
この記述は、JavaScriptでは、おなじみのimportの記述です。

<script setup lang="ts">
  // 作成した「testItem.vue」をインポート
  import testItem from '@/components/testItem.vue'
</script>

パスに記載されている、「@」は「src」フォルダを表します。
相対パスでも読み込みができますが、ファイルの置き場所が変わったりすると修正する必要があるため、「@」で記述しておくとメンテナンスが楽です。

ワンコ
ワンコ

テンプレートブロック解説

scriptブロックでインポートした、コンポーネントを表示しています。
インポートした名称と同じタグを記述することでコンポーネントを組み込むことができます。

<template>
  <div>
      <!-- インポート名と同じタグを記述する -->
      <testItem/>
  </div>
</template>

不要なブロックは削除しても大丈夫です。
「App.vue」にはcssを記載していないので、スタイルブロックは削除しました。

ニャンコ
ニャンコ

Vue3コンポーネントの複数読込

コンポーネントは、好きな場所に好きな数呼び出すことができます。

<script setup lang="ts">
  // 作成した「testItem.vue」をインポート
  import testItem from '@/components/testItem.vue'
</script>

<template>
  <div>
      <testItem/>
      <testItem/>
      <testItem/>
  </div>
</template>
コンポーネント複数読込

コンポーネントを複数読み込んでいるのが分かります。
サンプルのコンポーネントは特に何も処理を記述してないので、読み込んだところで何か起こるわけでもないですが、複数読み込めることを確認しました。

このようにVueの開発は様々なコンポーネントを組み合わせて開発していきます。

コンポーネントの概要

どれくらいの細かさでコンポーネントを分けるかはプロジェクト次第です。
例を挙げると・・
・テキストボックス一つをコンポーネントとしたり
・テキストボックスを含めたセクションごとコンポーネントとしたり
・極端に言えば、1ページ丸ごとコンポーネントとして扱うことも可能です。

ワンコ
ワンコ

リアクティブシステム

ref()関数

リアクティブシステムとは、変数の値が変更された際に、自動で画面表示を変えてくれるシステムで、Vueシステムの根本をなすシステムです。
Vueを利用する上で重要な仕組みなので、このシステムを先ほどの「testItem.vue」コンポーネントで利用します。
「testItem.vue」の内容を以下のように変更します。

<script setup lang="ts">
// vueシステムから ref関数をインポート
import {ref} from "vue";

// リアクティブな変数のセット
let num = ref(0);

// 1~10 までのランダムな数字を入れるメソッド(関数)
const calc = ()=> {
  num.value = Math.floor(Math.random() * 10) + 1;
}

// 1秒おきに実行
setInterval(calc,1000)
</script>

<template>
    <!-- リアクティブ変数を表示 -->
    <p class="">数字:<span>{{ num }}</span></p>
</template>

ファイルを変更した後は、実行して確認します。
1秒ごとにランダムな数字が表示されているのが分かると思います。
このように変数の値の変化と連動して、画面表示をリアルタイムで切り替えてくれる便利なシステムが、リアクティブシステムです。

実行結果

今回のコンポーネントの中身を分けて解説します。

scriptブロック解説

Vueシステムから、「ref関数」をインポートしています。
Vueでは必要な処理をインポートして利用します。
ref関数は、テンプレートブロックで表示するリアクティブ変数を定義するための関数です。

// vueシステムから ref関数をインポート
import {ref} from "vue";

このリアクティブな変数の事をテンプレート変数と呼んだりします。
今後は、このブログでもテンプレート変数と呼称します。

ニャンコ
ニャンコ

ref関数を使う場合、引数に値を渡すことで、初期値を設定することができます。
今回は初期値「0」を設定しています。

// リアクティブな変数のセット
let num = ref(0);

1から10のランダムな値を設定する関数を作成しました。
その関数の中身は、Vue.jsとは関係ない、素のJavaScriptの関数なので、説明を省きます。

注目したいのが、作成したテンプレート変数に値をセットしている部分です。
scriptブロック内で、テンプレート変数の値を使用したり、代入する場合は、「.value」を付けます。

// 1~10 までのランダムな数字を入れるメソッド(関数)
const calc = ()=> {
  num.value = Math.floor(Math.random() * 10) + 1;
}

1秒ごとに「calc」関数を実行して、テンプレート変数に値をセットしています。

// 1秒おきに実行
setInterval(calc,1000)

テンプレートブロック解説

{{ }} で囲むことで、scriptブロックで定義したテンプレート変数を表示することができます。
テンプレートブロックの場合は、「.value」を付ける必要はありません

<template>
    <!-- リアクティブ変数を表示 -->
    <p class="">数字:<span>{{ num }}</span></p>
</template>

この「{{ }}」の部分をマスタッシュ(口ひげ)構文と言います。
横から見たときに口ひげに見えるからだそうです。
口ひげかこれ?

ニャンコ
ニャンコ

コンポーネントを複数配置してみる

次に今作成した「testItem.vue」コンポーネントを複数App.vueに配置しています。

<script setup lang="ts">
import testItem from '@/components/testItem.vue'
</script>

<template>
  <div>
      <!-- コンポーネントを複数配置 -->
      <testItem/>
      <testItem/>
      <testItem/>
  </div>
</template>

実行結果

同じコンポーネントを読み込んでいますが、それぞれのコンポーネントが別の値を持って動作してることが分かると思います。

それぞれのコンポーネントが独立して動くので、コンポーネントとして取り回しがしやすいですね。

ワンコ
ワンコ

reactive()関数

ref'()関数と似たもので、reactive()関数があります。
こちらもリアクティブな変数を定義する関数です。
refとreactiveネットで検索すると、どちらを使う?みたいな記事があるほど用途が似ています。
新たに「testItem2.vue」というコンポーネントファイルを作成して挙動を確認しましょう。

reactive()関数は、オブジェクトをリアクティブ変数として扱う際に使用します。

ワンコ
ワンコ
<script setup lang="ts">
// reactiveインポート
import {reactive} from "vue";

// reactive関数の初期値としてオブジェクト設定
let num = reactive(
  {
    single:0,
    twice:0,
    triple:0
  }
);

// 1~10までの値を出して、それぞれ2倍と3倍にした値を
//reactive関数で作成した変数にセット
const calc = ()=> {
  const result = Math.floor(Math.random() * 10) + 1;
  num.single = result
  num.twice = result* 2;
  num.triple = result * 3;
}

setInterval(calc,1000)

</script>

<template>
    <!-- 作成したテンプレート変数を出力 -->
    <p class="">数字:<span>{{ num.single }}</span></p>
    <p class="">数字(2倍):<span>{{ num.twice }}</span></p>
    <p class="">数字(3倍):<span>{{ num.triple }}</span></p>
</template>

作成したコンポーネントを、App.vueで読み込んで表示させます。

<script setup lang="ts">
import testItem2 from '@/components/testItem2.vue'
</script>

<template>
  <div>
      <testItem2/>
  </div>
</template>

実行結果

オブジェクトを丸ごとリアクティブ化できました。

ニャンコ
ニャンコ

scriptブロック解説

ref()関数の処理と大きくは違わないのでポイントだけ解説します。
refと同じようにreactive関数をvueシステムからインポートします。
引数は、オブジェクトを指定します。

// reactiveインポート
import {reactive} from "vue";

// reactive関数の初期値としてオブジェクト設定
let num = reactive(
  {
    single:0,
    twice:0,
    triple:0
  }
);

関数の中で、ランダムな数字を計算して、それぞれ1倍、2倍、3倍の値を、用意したテンプレート変数に代入しています。
通常のオブジェクトのようにプロパティにアクセスして、データのやり取りが可能です。
ref()と違って、「.value」は必要ありません。

const calc = ()=> {
  const result = Math.floor(Math.random() * 10) + 1;
  num.single = result
  num.twice = result* 2;
  num.triple = result * 3;
}

テンプレートブロック解説

テンプレートブロックでは、ref()の時と同じようにマスタッシュ構文で、プロパティを指定して値を出力します。

<template>
    <!-- 作成したテンプレート変数を出力 -->
    <p class="">数字:<span>{{ num.single }}</span></p>
    <p class="">数字(2倍):<span>{{ num.twice }}</span></p>
    <p class="">数字(3倍):<span>{{ num.triple }}</span></p>
</template>

computed()(算出プロパティ)

リアクティブ関連で、頻繁に使うものにcomputed()があります。
computed()は、様々な式の計算結果をリアクティブに返してくれます

「testItem.vue」コンポーネントを改修して、動作を確認します。

<script setup lang="ts">
// computed インポート
import {ref,computed} from "vue";

let num = ref();

const calc = ()=> {
  num.value = Math.floor(Math.random() * 10) + 1;
}

// 算出プロパティを用意
// 5より大きいかどうかを判定して、文言を返す
const Note = computed(
	() => {
		let Note;
    if(num.value > 5) {
			Note = "5より大きい";
		} else {
      Note = "5より小さい";
    }
		return Note;
	}
)

setInterval(calc,1000)

</script>

<template>
    <!-- 算出プロパティもマスタッシュ構文で表示 -->
    <p class="">数字:<span>{{ num }}</span>({{ Note }})</p>
</template>

実行結果

算出プロパティの基本的な構文はこのようになっています。
computed()の引数の中に、処理を作成して、計算結果を必ずreturnで返します。

const 変数名 = computed(
	() => {
		return 計算結果;
	}
)

算出プロパティは、読み取り専用です。
算出プロパティの変数に値を入れようとするとエラーになります。

ニャンコ
ニャンコ
const Note = computed(
	() => {
		let Note;
    if(num.value > 5) {
			Note = "5より大きい";
		} else {
      Note = "5より小さい";
    }
		return Note;
	}
)
// これはエラーになります。
Note = "7より大きい"

長くなったので今回はここまで。
次回はテンプレートブロックで使用する様々な要素についてです。

ニャンコ
ニャンコ

参考書籍

今回の記事作成にあたっての参考書籍はこちら。
私はVue3の全てもをこの本から学んでるので、さらに詳しくVue3を学びたい方はこちらがオススメです。

参考書籍

-Vue.js
-, ,