Lesson 5

Vite で Vue プロジェクトを作成する

Lesson 5 Chapter 1
はじめに

実際に、Vite で Vue プロジェクトを作成する前に、本チャプターでは「Vite とは何か」などの基本的なことを説明します。

1. Vite とは

Vite(ヴィート)とは、Vue の製作者であるエヴァン・ヨー(Evan You)氏が開発し 2020 年に発表されたビルドツール(Vite 公式)で、Vue でプロジェクトを作成する際の公式ツールとされています。

vue_5-1-1.png

当初は Vue 向けのライブラリとして開発されましたが、現在は Vanilla JS(※)や React、Svelte など他の JavaScript フレームワークでも使用できるようになっています。

Vanilla JS とは

ライブラリ等を使用しない素の JavaScript のことを Vanilla JS(バニラ JS)といいます。
語源は、アイスクリームの標準的な種類であるバニラから来ており、何らのカスタマイズ・改変をしていないという意味合いがあります。

2. ビルドツールとは

Vite の紹介に出てきた「ビルドツール」とは何かについて簡単に説明しておきます。

2-1. ビルドツールの役割

今までの学習ではビルドツールは使用せず、1 つの HTML ファイルにソースコードを記載してそのまま実行してきました。

しかし、現在のフロントエンド開発では、複数の JavaScript ファイル(モジュール※)に分けてアプリケーションを作成することがほとんどです。 1 つのファイルごとに機能を持たせ、必要に応じて他のファイルをインポートして使用します。

このように、複数の JavaScript ファイルで構成されたアプリケーションは、ソースコードをそのまま使用せず、「実行用の JavaScript」に変換して使用するのが一般的です。

モジュール

モジュールとは日本語で「部品」という意味になります。
JavaScript におけるモジュールは「ある機能を有した 1 つの JavaScript ファイル」と考えて差し支えありません。

また、TypeScript を使用した場合は、そのままではブラウザで実行できないため、JavaScript へのコンパイル(言語変換)を行わないとコードの実行自体ができません。

このような変換を自動で行ってくれるのが「ビルドツール」となります。 JavaScript におけるビルドツールで提供される機能としては、主に次のようなものがあります。

No 機能 簡単な説明
1 バンドル(bundle) 複数のファイルの依存関係を解決し 1 つのファイルにまとめる(外部ライブラリも含めて)。
2 トランスパイル(transpile) ソースコードを他の言語に置き換える(バージョンの互換や TypeScript → JavaScript の変換)。
3 ミニファイ(minify) ソースコードを圧縮し軽量化する(不要なコードを削除し、冗長な記載を短縮化)。

2-2. バンドル(バンドラー)

上の表のうち「バンドル」という言葉は特に重要です。
かつての JavaScript には他のファイルを読み込む機能がありませんでした。 その後、2009 年に発表された Node.js(次の Chapter 参照)や 2015 年に導入された ES Modules という仕組みにより、他の JavaScript ファイルをインポートして使用できるようになりました。

しかし、当時はそのような複数ファイルの読み込みに対応したブラウザは少なく、アプリケーションを実行するには、複数のファイルを 1 つのファイルに変換する処理が必須とされていました。
そのように、1 つのファイルに統合する処理を「バンドル」(「束ねる」という意味)といい、それを実行するツールを「バンドラー」と呼んでいます。

2-3. Webpack と Babel について

JavaScript の代表的なビルドツールとして Webpack と Babel の 2 つがあります。

① Webpack

Webpack はモジュールバンドラーです。
つまり、複数のファイル(モジュール)の依存関係を解決して統合するバンドル(bundle)の機能を提供します。
また、ソースコードを圧縮し軽量化するミニファイ(minify)の機能なども有しています。
その他様々な拡張ができ、現在の Web 開発には必須のツールとなっています。

② Babel

Babel は、バージョンの差異を吸収するトランスパイル(transpile)の機能を有しています。
開発環境で使用した JavaScript のバージョンに、ブラウザが対応していないことはよくあります。 このような場合に備えて、Babel は、新しい JavaScript のバージョンを下位互換し、ブラウザのサポートが無くても動作できるようにしてくれます。

3. Vite の特徴

Vite は単なるビルドツールではなくて、Vue の開発に必要な様々な機能を提供してくれます。主な特徴は次のとおりです。

  • 開発環境のおいて高速な起動・更新が可能
  • IE にも対応した本番用のビルドが可能(Webpack、Babel の代替)
  • 簡易に Vue プロジェクトを作成することができる(Vue CLI の代替※)

Vite は、フランス語で「素早い」という意味を持っており、開発時のバンドルを最小限に抑えるなどして Webpack よりも起動・更新の速度がかなり高速になっています(詳しくは 公式 を参照)。

また、従来は、Vue CLI、Webpack、Babel の 3 つのツールを組み合わせて行っていた Vue プロジェクトの作成が、Vite のみで全て実行できるようになっており、高速かつ利便性の高いライブラリとして急速に人気を高めています。

Vue CLI について

以前は、Vite ではなく「Vue CLI」が、Vue の公式ツールとされていました。
Vue CLI も Vue の開発環境を作成するツールであり、Webpack や Babel を使用した複雑なビルドの処理を簡易に実行することができるようになっています。

現在も使用可能ですが、メンテナンスモードに入っており、新しい機能の追加などは行われない状態となっています(Vue CLI 公式 でも、新しいプロジェクトを作成する際は Vite を使用することを推奨しています)。

Lesson 5 Chapter 2
Vite プロジェクト作成

このチャプターでは、実際に Vite を使用して、Vue プロジェクトを作成していきます。
Vite を使用するには、先に Node.js をインストールする必要がありますので、そこから説明をしていきます。

1. Node.js のインストール

Node.js はサーバーサイドで JavaScript を実行できるようにしたプラットフォームです。
ダウンロードするために、以下の URL から Node.js 公式ページ開いてください。
https://nodejs.org/ja/

1-1. Node.js のダウンロード

以下のページが開いたら、左側の「LTS 推奨版」の方をクリックしてください(実行時期によりバージョン番号は異なります)。

vue_5-2-1.png

クリックしたら、インストーラーのダウンロードが開始されます。

1-2. Node.js のインストール

ダウンロードできたら、ファイルをダブルクリックしてインストーラーを起動します。
基本はデフォルトのままでインストールを進めれば OK です。「Next」をクリックします。

vue_5-2-2.png

ライセンスの同意を求められます。
特に問題なければチェックをして「Next」をクリックします。

vue_5-2-3.png

以下の画面でインストール先のフォルダを選択できます。
問題なければ、このまま「Next」で OK です。

vue_5-2-4.png

ここではインストール内容をカスタマイズできます。
こちらもデフォルトのままで「Next」をクリックします。

vue_5-2-5.png

以下では「必要なツールを自動的にインストールするか」を聞かれます。
こちらもチェックをしないでデフォルトのまま「Next」で OK です。

vue_5-2-6.png

「Install」ボタンをクリックすると、インストールが開始します。 完了まで少し待ちます。

vue_5-2-7.png

次の画面が出ればインストール完了です。「Finish」をクリックしてください。

vue_5-2-8.png

1-3. Node.js がインストールできたかを確認する

Node.js がインストールできたかを確認するために、PowerShell またはコマンドプロンプトを開きます。

① Node.js のバージョンを確認する

まず、Node.js のバージョンを確認するコマンド node --version を実行します(コマンドは短縮形 node -v でも構いません)。

> node --version
v18.12.1

以上のように v18.12.1 というようなバージョン番号が表示されれば OK です(バージョン番号はインストールの時期により異なります)。

② npm のバージョンを確認する

次に、npm(※)のバージョンを確認するコマンド npm --version を実行します(コマンドは短縮形 npm -v でも構いません)。

> npm --version
8.19.2

以上のように 8.19.2 というようなバージョン番号が表示されれば OK です(バージョン番号はインストールの時期により異なります)。

npm とは

npm とは Node Package Manager を略したもので、その名のとおり Node.js で使用するパッケージ(ライブラリ)を管理するツールとなります。
npm のコマンドを使用することで様々なパッケージのインストールができ、パッケージ間の依存関係の管理も行うことができます。

以上で Node.js のインストールは完了です。

2. VSCode に拡張機能(Volar)をインストールする

Vite でプロジェクトを作成する前に、VSCode に Volar という拡張機能を入れておきます。
これは Vue3 用の拡張機能で、コードに色がつき見やすくなるなど色々と便利になります。

vue_5-2-8-1.png

リンク先から Install ボタンを押すことでもインストールはできますが、一応、一般的な方法を紹介しておきます。

VSCode を開いて、左側の拡張機能のアイコンをクリックします。

vue_5-2-8-2.png

検索ボックスに「Volar」と入力して「Vue Language Features (Volar)」という拡張機能を探します。
見つかったら、その表示の右側にある「Install」ボタンをクリックしてください。

vue_5-2-8-3.png

少し待てば、インストールが完了します。

3. Vite でプロジェクトを作成する

それでは、Vite を使用して Vue プロジェクトの作成を行いましょう。
PowerShell またはコマンドプロンプトを開いてください。

vue_5-2-9.png

まず、プロジェクトを作成するフォルダに移動します。
どこでも構いませんが、ここでは既に作成している C:\vue_lesson フォルダに移動して、そこにプロジェクトを作成します。

① 作業フォルダに移動

フォルダ(ディレクトリ)を移動するコマンドは、cd ディレクトリ です。
次のように、cd C:\vue_lesson と入力してフォルダを移動してください。

PS C:\Users\username> cd C:\vue_lesson
PS C:\vue_lesson>

② Vite プロジェクト生成コマンドの実行

Vite プロジェクトを作成するコマンドは次のとおりです(Vite 公式 参照)。

$ npm create vite@latest

実行すると、次のようにプロジェクト名を聞かれます。

vue_5-2-10.png

③ プロジェクト名の指定

プロジェクト名は何でも良いのですが、ここでは「vite-sample」と入力して Enter キーを押します。

PS C:\vue_lesson> npm create vite@latest
? Project name: » vite-sample

④ フレームワークの選択

すると、次のようにフレームワークの選択肢が現れます。
上から、Vanilla,Vue,React ... と表示されますので、PC の方向キー(カーソルキー)で「Vue」を選択して Enter キーを押します。

vue_5-2-11.png

⑤ プログラム言語等の選択

今度は、JavaScript や TypeScript などの選択を求められます。
ここでは、JavaScript を使用するので、そのまま Enter キーを押します(表示順が変更になっていたら、適宜 JavaScript を選択してください)。

vue_5-2-12.png

これで、Vue プロジェクトが自動で作成されます。

⑥ プロジェクト作成の完了

プロジェクト作成完了後の PowerShell(コマンドプロンプト)は次のように表示されていると思います。

PS C:\Users\username> cd C:\vue_lesson
PS C:\vue_lesson> npm create vite@latest
√ Project name: ... vite-sample
× Select a framework: » Vanilla
✖ Operation cancelled
PS C:\vue_lesson> npm create vite@latest
√ Project name: ... vite-sample
√ Select a framework: » Vue
√ Select a variant: » JavaScript

Scaffolding project in C:\vue_lesson\vite-sample...

Done. Now run:

  cd vite-sample
  npm install
  npm run dev

Done. Now run: に続く末尾の 3 つのコマンドを実行するとサーバが立ち上がるのですが、このレッスンでは VSCode から開きます。 続きは、次のチャプターをご覧ください。

Lesson 5 Chapter 3
ローカルサーバ起動と内容の確認

このチャプターでは、前チャプターで作成したプロジェクトをローカルサーバで起動してみます。 そして、自動生成されたコードの中身を確認していきます。

1. 作成したプロジェクトをローカルサーバで起動する

1-1. プロジェクトを作成したフォルダの確認

プロジェクトを作成したフォルダを見てみましょう。
フォルダを見ると「vite-sample」という新しいフォルダが作成されているはずです。

vue_5-3-1.png

1-2. VSCode からプロジェクトを開く

上記の vite-sample フォルダを VSCode から開いてください。
(既に VSCode が開いていたら、vite-sample フォルダを VSCode にドラッグアンドドロップすることでも開けます)

無事に開けたでしょうか。
正しくフォルダが開けるとヘッダー部分に「vite-sample」というプロジェクト名が表示され、左側のソースツリーのルート部分にも「VITE-SAMPLE」とプロジェクト名が表示されているはずです。

vue_5-3-2.png

1-3. VSCode のターミナル(Terminal)を開く

VSCode のメニューから「Terminal」をクリックして「New Terminal」を選択してください。

vue_5-3-3.png

すると次のようにターミナル(Terminal)が開きます。
ターミナル(Terminal)は、PowerShell や コマンドプロンプトと同じようにコマンドが打てる画面です。

vue_5-3-4.png

さて、前チャプターでプロジェクトを作成した際に、次の 3 つのコマンドが表示されていました。

cd vite-sample
npm install
npm run dev

VSCode で開いたターミナルでは、PS C:\vue_lesson\vite-sample> というように、既に vite-sample フォルダに入っているため、1 行目の cd vite-sample は実行不要です。
残り 2 つのコマンドについて、以下で確認していきます。

1-4. package.json を確認する

プロジェクトを作成した直後は、まだ、プロジェクトを動かすために必要なライブラリがインストールされていない状態となります。

Node.js の実行に必要なライブラリは package.json というファイルに記載されています。
VSCode 左側のソースツリーにある package.json をクリックしてファイルの中身を確認してみましょう。

vue_5-3-5.png

記述されている項目について、上から確認すると、次のようになります。

No プロパティ 説明
1 name プロジェクト名(パッケージ名)です。作成時に指定した「vite-sample」がそのまま入っています。
2 private Node.js のパッケージは全世界に公開することができます。private を true にしておくことで間違って公開することを防ぐことができます。
3 version プロジェクト(パッケージ)のバージョンを指定します。
4 type "type": "module" と指定することで、パッケージが ES Modules として認識されます(現在はわからなくとも大丈夫です)。
5 scripts 実行コマンドの別名を指定することができます。
6 dependencies 使用するライブラリとバージョンを記述します。
7 devDependencies 使用するライブラリとバージョンを記述します(開発環境でしかインストールしないもの)。

ここでライブラリに関係するのは、No 6「dependencies」と No 7「devDependencies」の 2 つです(下記)。

  "dependencies": {
    "vue": "^3.2.45"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^4.0.0",
    "vite": "^4.0.0"
  }

以上から、このプロジェクトに必要なライブラリは、次の 3 つということになります。

  • "vue": "^3.2.45"
  • "@vitejs/plugin-vue": "^4.0.0"
  • "vite": "^4.0.0"

1-5. npm install の実行

上記の package.json に記載されたライブラリを一括でインストールするのが npm install というコマンドとなります。
ということで、以下のようにターミナルから npm install を実行してみましょう。

vue_5-3-6.png

少し時間が掛かりますが、上記のように表示されたらインストール完了となります。

インストールしたら、以下のように node_modules というフォルダと、package-lock.json というファイルが自動生成されます。

vue_5-3-7.png

node_modules には、インストールしたライブラリのコードが格納されています。
package-lock.json には、実際にインストールしたパッケージとバージョン情報が記載されます。

1-6. ローカルサーバの起動

それでは、プロジェクトをローカルサーバで起動させてみましょう。
起動するには、npm run dev というコマンドを実行します。

vue_5-3-8.png

実行すると、ローカルサーバでアプリケーションが起動し、ターミナルは上記のような状態となります。 ここに表示された http://localhost:5173/ を開くことで、アプリケーションを表示することができます。

開き方は自由ですが、「ctrl」キーを押したままターミナルの URL をクリックすることで簡単に開くことができます(もちろん、直接 URL をブラウザに入力しても OK です)。
以下のような画面が表示されれば成功です。

vue_5-3-9.png

骨組みだけのアプリケーションですが、以下の「count is 0」のところをクリックすると、数字が 1 つずつ増えていきます。

vue_5-3-10.png

1-7. ローカルサーバの停止

それでは、ローカルサーバを停止しておきましょう。
VSCode のターミナル上で、「ctrl」と「c」を同時に押してください。

vue_5-3-11.png

すると、赤枠のところのようにコマンドが打てる状態に戻ります。
再度、サーバを起動させる場合は、最初と同じく npm run dev コマンドで OK です(ここでは再起動しません)。

2. Vite で作成した Vue プロジェクトの内容確認

ここでは、作成された Vue プロジェクトのコードの中身を確認して、その構造を把握していくようにします。
たくさんファイルがあって難しそうな印象を持つかもしれませんが、基本的なところはこれまで HTML ファイルで作成してきたプログラムと変わりません。

2-1. エントリーポイント(index.html)

エントリーポイントとは、プロジェクトを起動したときに「一番最初に実行される場所」のことをいいます。

VSCode 左側のソースツリーから index.html を開いてみてください(下図)。

vue_5-3-12.png

Vite で生成したプロジェクトは、デフォルトで index.html ファイルがエントリーポイントとなります。
このファイルの <body> タグの中身は次のようになっています。

<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>
</body>

これまでのレッスンで作成してきた HTML ファイルと共通点があるのが分かりますでしょうか。

① テンプレートの表示部分

まず、テンプレートの表示用に <div id="app"></div> という <div> タグが用意されています。 中身の HTML はありません。この中身は、別のファイルで記載してここに読み込ませることになります。
このプロジェクトで表示されるテンプレートは、全てここに表示されます。

② スクリプトの記述部分

次に、スクリプトの記述用に <script type="module" src="/src/main.js"></script> という <script> タグが用意されています。
スクリプトは記述されておらず、代わりに /src/main.js を読み込むようにされています。
このプロジェクトで作成する JavaScript は全てここから読み込まれます。

index.html ファイルの内容はとてもシンプルですが、このファイルが本アプリケーションのベースとなっていることを把握しておきましょう。

2-2. main.js ファイル

続いて、先ほど index.html で指定されていた main.js ファイルを見てみましょう。
main.js ファイルは src ディレクトリの直下にあります。

vue_5-3-13.png

この main.js ファイルは、本アプリケーション全体の JavaScript のベースとなり、最初に実行されるファイルとなります。
広義の意味ではこの main.js もエントリーポイントと言えます。

記述内容は、以下の 4 行です。
これも、これまでのレッスンで作成してきた HTML ファイルと基本部分は変わりません。

main.js
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

createApp(App).mount('#app')

参考までに、これまでのレッスンで作成してきたスクリプトは次のような形式でした。

参考: CDN の場合の記述
<script>
  const { createApp } = Vue

  const App = {
    setup() {
      const message = 'Hello World!'
      return {
        message
      }
    }
  }
  createApp(App).mount('#app')
</script>

以下、2 つの記述を比較しながら内容を確認していきましょう。

① Vue 本体の読み込み部分

Vite プロジェクトは、以下のところで Vue の本体を読み込んでいます。

import { createApp } from 'vue'

この import の記述は、node_modules フォルダに格納されている Vue の本体ファイルから createApp 関数をインポートするものです。

なお、これまでのレッスンの記述では、次のように記載していました。

参考: CDN の場合の記述
const { createApp } = Vue

これもやっていることは同じで、CDN で読み込んだ Vue 本体のファイルから createApp 関数を取り出しているというものです。

② アプリケーションインスタンスの生成とマウント

Vite プロジェクトでは、以下のところでアプリケーションインスタンスを生成し、テンプレートにマウントをしています。

createApp(App).mount('#app')

createApp 関数で指定する App コンポーネントは、別のファイル App.vue に記載されており、以下の記述でインポートしています。

import App from './App.vue'

この App.vue コンポーネントの内容は、次の項で見ていきます。

なお、これまでのレッスンの記述は以下のとおりで、全く同じですね。

参考: CDN の場合の記述
createApp(App).mount('#app')

③ CSS ファイルの読み込み

CSS ファイルの読み込みは、Vite プロジェクトの方のみ記載されています。

import './style.css'

この記述で style.css ファイルで指定したスタイルをアプリケーション全体に適用することができます。

2-3. App.vue コンポーネント

次に main.js ファイルで読み込まれている App.vue コンポーネントを確認しましょう。
これは、必ず最初に読み込まれる「ルートコンポーネント」となります。

vue_5-3-14.png

コード自体は、今まで見てきたものとは異なる内容となっていると思います。
この .vue という拡張子を持つファイルは「単一ファイルコンポーネント」と呼ばれるもので、この内容と書き方については次のチャプターで説明をします。

分からない用語などが少し出てきましたが、以上で、プロジェクトがどのような導線に従って起動するかなど、Vite プロジェクトの構成の大筋は理解できたのではないかと思います。

Lesson 5 Chapter 4
単一ファイルコンポーネントとは

このチャプターでは「単一ファイルコンポーネント(Single File Component)」について学んでいきます。

1. 単一ファイルコンポーネントの概要

前チャプターで確認した App.vue コンポーネントの内容は次のとおりでした。
.vue 拡張子を持つこのファイルは「単一ファイルコンポーネント」と呼ばれるものです。

vue_5-3-15.png

コードは赤枠部分の 3 つのブロックに分割することができます。

No タグ 分類 説明
1 script スクリプト(ロジック) JavaScript で画面表示ロジックを記述
2 template テンプレート HTML を生成するテンプレート部分を記述
3 style スタイル CSS でスタイルを記述

このように、単一ファイルコンポーネントを使用することで、Vue コンポーネントのテンプレート、スクリプト、スタイル を 1 つのファイルにまとめることができます。

なお、単一ファイルコンポーネントは、その英語表記の Single File Component の頭文字をとって「SFC」と省略されたり、その拡張子から「.vue ファイル」と呼ばれたりします。

Vite を使用した場合は、デフォルトでこの単一ファイルコンポーネントを使用することになります。

2. 各ブロックの記載内容

それでは、App.vue の記載内容をざっと確認していきます。

① template

まずは、テンプレート(template)のところから見ていきましょう。
見てのとおり、内容はほぼ HTML です。

<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <HelloWorld msg="Vite + Vue" />
</template>

2 つの <a> タグでは、それぞれ Vite のロゴと Vue のロゴを表示しているだけです。

末尾の <HelloWorld msg="Vite + Vue" /> のところは、Vue の機能を使用した記述で、子コンポーネント HelloWorld を呼び出して、テンプレート内に表示するようにしています。 タグ内の msg="Vite + Vue" は、msg という props の値に「Vite + Vue」を指定して子コンポーネントにデータを渡しています(props の詳細は lesson 6 で学習します)。

② script

次にスクリプト(script)の部分です。
最初の script タグに指定されている <script setup> という記述は「script setup 構文」を使用するという指定になっています。

<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>

上記でインポートしているのは、子コンポーネントとして使用する HelloWorld.vue であり、これは先ほど見た template 内で使用されるものです。 なお、この記述方法は script setup 構文の特有の書き方であり、記述が一部簡略化されています。

「setup() 関数」と「script setup 構文」の違い

名称が似ていて混同しがちですが、今までのレッスンで使用してきた「setup() 関数」と、今回登場した「script setup 構文」は異なるものです。

setup() 関数は「Vue アプリケーションの中核となる機能」で、その中にリアクティブな変数やメソッドなどを定義してテンプレート側に渡すことができるものです。

script setup 構文は「setup() 関数などを簡単に書けるようにした記述方式」のことです。
単一ファイルコンポーネント内でのみ利用できる書き方で、Vite などのビルドツールを使用することが前提となります。

つまり、setup() 関数は機能のことを差し、script setup 構文は記述方式のことを差すことを頭に入れておきましょう。

比較として、これまでのレッスンで解説した記述方法で書くと、以下のように components: プロパティの中に、子コンポーネントを記載する必要がありました(Lesson 4 参照)。

参考: CDN を使用した場合の子コンポーネントの指定方法
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
  components: {
    HelloWorld
  }
};
</script>

script setup 構文を使用することで、冗長な記述を減らして見通しの良いコードにすることができます。 この script setup 構文については、Chapter 6 で詳細を見ていきます。

③ style

最後に、スタイル(style)のところを見てみましょう。

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

これは見てのとおり、単に CSS を指定するだけのブロックになります。

なお、最初の style タグ <style scoped> に指定されている scoped は「このコンポーネント内のみに CSS を適用する」という指定になります。
つまり、ここで指定した CSS は他のコンポーネントには影響を与えないということになります。

Lesson 5 Chapter 5
Composition API について

以前のレッスンでも少し説明をしましたが、このチャプターでは、Composition API とは何かについて、従来の Options API と比較しながら詳しく見ていきます。

1. Options API と Composition API

Vue 2 では「Options API」というものが使用されていましたが、Vue 3 からは「Composition API」というものが新たに導入されました。
これらの 2 つの違いを大雑把に言えば「コンポーネント形式が異なる」点にあります。

以下、それぞれの特徴と違いについて見ていきましょう。

1-1. Options API(主に Vue 2 で使用)

Options API は、次のような書き方になります。

const app = new Vue({
  el: '#app',
  data() {
    return {
      unitPrice: 200,
      quantity: 0
    }
  },
  methods: {
    add() {
      this.quantity++
    }
  },
  computed: {
    payment() {
      return this.unitPrice * this.quantity
    }
  }
})

大きな特徴としては、eldatamethodscomputed などの「オプション」を定義して、それぞれの中でコードを記述していく形式となっています。

主なオプションとしては、次のようなものがあります。

No オプション 説明
1 el オプション Vue インスタンスと紐づける id 名または class 名を指定する。
2 date オプション リアクティブ変数を定義する。
3 methods オプション メソッドを記述する。
4 computed オプション 算出プロパティを記述する。
5 watch オプション 監視プロパティを記述する。
6 props オプション 親コンポーネントから受け取る値を定義する。
7 created,mounte オプション ライフサイクルフックを記述する。
8 template オプション テンプレートを記述する。

コンポーネントの規模が大きくない場合は処理の記述が定型的になり、分かりやすいという利点があります。

しかし、コンポーネントの規模が大きくなると 1 つの処理に関連するロジックが、その内容により datamethodscomputed などに分かれて記述されることから、記述場所が遠く離れてしまい、処理を追うのが困難になるなどの問題がありました。

また、data で定義した変数を methods で使用するなど、異なるオプション間でデータの受渡しを行うには、this を介して使用する必要があるため、メソッド等を View(テンプレート)と切り離して使用することができないという問題もありました。

1-2. Composition API(主に Vue 3 で使用)

Composition API では、次のように「setup() 関数」の中に処理をまとめて書きます。

Vue.createApp({
  setup() {
    const unitPrice = 200
    const quantity = ref(0)
    const payment = computed(() => unitPrice * quantity.value)
    const add = () => quantity.value++
    return {
      unitPrice,
      quantity,
      payment,
      add
    }
  }
}).mount('#app')

Composition API においては this を使用しないため、各ロジックをコンポーネントから独立して実行することができます。
また、オプションに分けて記述する必要がないことから、関連するロジックを同じ場所に記載することもできます

このように、Composition API においては、「ロジックをカプセル化して再利用しやすくなるとともに、見通しの良いコードを書くことができる」ようになっています。

また、Vue 3 ではデフォルトで TypeScript に対応しているなどの改良もされており、処理速度も早くなっています。

なお、Composition API については、最新の Vue 3.2 で導入された「script setup 構文」を使用することで、よりシンプルで分かりやすい記述をすることが可能となっています(script setup 構文については、次のチャプターで詳しく学習していきます)。

1-3. Options API は非推奨ではない

今後は Composition API を使用することが一般的になっていくものと思われます。
しかし、Options API は非推奨となっているわけではなく、Vue 3 でも Options API は使用できるようになっています。
規模の小さい開発では Options API を採用することも選択肢の 1 つとなり得るでしょう。

2. Vue 2 と Vue 3

Composition API は Vue 3 において実装されたコンポーネント形式であるため、大雑把に言うと「Vue 2 は Options API」で「Vue 3 は Composition API」と捉えて問題ありません。

ただし、2022 年 7 月に公開された Vue 2.7 では、Vue 3 の Composition API が使用できるようになっています。
また、先述のように Vue 3 においては、Composition API だけでなく Options API を使用することもできるようになっています。

あまり意識しなくとも大丈夫ですが、実際上は、Vue 2 と Vue 3 の互換性などの観点も含めて、柔軟な対応がされているということは把握しておいた方が良いでしょう。

Lesson 5 Chapter 6
script setup 構文

前のチャプターでも出てきましたが、ここでは script setup 構文について学習をしていきます。

1. HelloWorld.vue コンポーネントを確認する

まず、script setup 構文がどのようなものかイメージを掴むために、App.vue の子コンポーネントである HelloWorld.vue を見ていきましょう。

1-1. HelloWorld.vue の描画範囲

HelloWorld.vue が描画しているのは下図の赤枠の部分となります。

vue_5-5-2.png

1-2. HelloWorld.vue のソースコード

ファイルは、src/components ディレクトリ内にありますので、開いてみましょう。

下図の緑枠 <h1>{{ msg }}</h1> の部分で「Vite + Vue」のメイン文字を表示しています。
msg には、親コンポーネントから渡される props の値が入っています。

もう一つの緑枠 <button type="button" @click="count++">count is {{ count }}</button> は、クリックの度にカウンターを 1 ずつ加算するボタンの部分です。
@clickv-on:click の省略記法で、クリック時に実行されるメソッドは count++ というように、直接 JavaScript 式が記載されています。

vue_5-5-1.png

① script setup 構文を確認する

このチャプターのテーマである「script setup 構文」は上記ソースコードの赤枠部分が該当します。抜き出すと次のとおりです。
最初の <script setup> で script setup 構文であることを定義しています。

<script setup>
import { ref } from 'vue'

defineProps({
  msg: String,
})

const count = ref(0)
</script>

親コンポーネントからデータを受け取る props は defineProps を使用して定義しています。 なお defineProps はインポートしなくとも使えます。

また、カウンターに使用している変数 count は、ref 関数を使用して定義しています。
これまでのレッスンでは setup() 関数内に変数を定義していましたが、script setup 構文の場合は <script setup> のタグ内に直接定義するだけで「setup() 関数内に記述したもの」として扱われます。
また、<script setup> タグ内で直接定義した変数やメソッドは、return で返さなくとも、テンプレート側で受け取ることができます。

② script setup 構文を使用しない場合の例

script setup 構文を使用しない場合は、次のように記述することが必要です。

<script>
import { ref } from 'vue'

export default {
  props: {
    msg: String
  },
  setup() {
    const count = ref(0)

    return {
      count
    }
  }
}
</script>

定義内容は同じですが、どうしてもコードの記述は増えてしまいます。

ざっとですが、何となく script setup 構文のイメージは掴めたのではないかと思います。以下、script setup 構文の仕様について詳しく見ていきます。

2. script setup 構文とは

2-1. 概要

script setup 構文について、簡単に言うと「setup()return などの定型的で毎回記述する内容は省いて、シンプルでわかりやすい書き方をすることができる構文」ということになります。

なお、変わるのは書き方だけで、「ビルド時に、setup() 関数などを用いた記述と同様になるように変換処理」してくれます。

2-2. Vue 公式の説明

参考として、公式サイトにおける script setup 構文の説明も確認してみましょう。
公式では次のように説明されています(SFC <script setup>)。

vue_5-5-3.png

公式サイトは、初学者向けに書かれているわけではなく、一般的には「フレームワークの仕様を正確に伝えること」が目的であるため、結構分かりにくい表現も多いです。

今の段階では概要さえ把握していただければ大丈夫ですが、公式サイトを見て分からない用語などを調べながら理解することも大事ですので、何かあれば公式サイトを確認するという癖もつけておきたいところです。

用語について

Vue 公式の解説で出ている用語について、把握しておいた方が良いものについて補足しておきます。

① コンパイル
コンパイルとは、一般に、人間が書いたソースコードをコンピュータが読める機械語に変換することをいいます。ただし、Vue においては、ビルド時のソースコードの変換処理が該当します(機械語には変換していません)。

② シンタックスシュガー(糖衣構文)
シンタックスシュガー(糖衣構文)とは、プログラミング言語で、読み書きのしやすさのために導入される書き方のことをいいます。書き方は変わっても命令内容は変わりません。

③ ボイラープレート
ボイラープレートとは、プログラミング言語において「使い回しされる定型文」のことで、基本的に変化しないもののことをいいます。

④ Composition API
Vue 3 で導入されたコンポーネントの形式で、setup() 関数などを使用してコードを記述するものをいいます。Vue 2 で使用していた Options API に代わるものです。

2-3. 基本構文

script setup 構文が使用できるのは、単一ファイルコンポーネントの場合のみです。
単一ファイルコンポーネントの script 部分のタグを <script setup> とすることで、script setup 構文が使用できます。

<script setup>
// ここにロジックを記述
</script>

3. script setup 構文における変数・メソッドの定義

script setup 構文では、変数・メソッドは script タグ内の直下に記述します。
こちらは、vite-sample プロジェクトに実際にコードを追加して確認していきます。

3-1. 単一ファイルコンポーネントの作成

src/components ディレクトリに、以下のように SetupTest.vue ファイルを追加します。

vue_5-5-4.png

作成した SetupTest.vue ファイルには、次の内容を記載しておきます。

<script setup></script>

<template>
  <p>SetupTest</p>
</template>

<style></style>

template 部分には、仮に「SetupTest」という文字が表示されるようにしておきます。

3-2. App.vue ファイルに子コンポーネントとして追加する

次に、SetupTest.vueApp.vue の子コンポーネントとして追加する処理を記述します。
App.vue ファイルを次のように修正します(修正内容は後述)。

vue_5-5-5.png

全てのコードを表示
App.vue
<script setup>
// import HelloWorld from './components/HelloWorld.vue'
import SetupTest from './components/SetupTest.vue'
</script>

<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <!-- <HelloWorld msg="Vite + Vue" /> -->
  <SetupTest />
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

① script の修正

script 部分の修正から見ていきます。
HelloWorld.vue のインポート部分はコメントアウトしておきます(ctrl キー + / キーでコメントアウトできます)。
その次の行に、SetupTest.vue のインポート文を追加します。

<script setup>
// import HelloWorld from './components/HelloWorld.vue'
import SetupTest from './components/SetupTest.vue'
</script>

② template の修正

次に、template 部分の修正です。
HelloWorld コンポーネントの挿入部分をコメントアウトします(ctrl + /)。
その次の行に、SetupTest を挿入するために <SetupTest /> を追記します。

  <!-- <HelloWorld msg="Vite + Vue" /> -->
  <SetupTest />

<SetupTest /> の記述部分は <SetupTest></SetupTest> としても OK です。
また、単一ファイルコンポーネントの場合には、コンポーネント名をキャメルケースで記載しても差し支えありません。

3-3. コンポーネントの表示テスト

ここで、コンポーネントの親子関係が正しく設定できたかを確認しておきます。 ターミナルを開き、コマンド npm run dev を打って、アプリケーションを起動してみましょう。

次のように、子コンポーネント SetupTest.vue の template に書いておいた「SetupTest」という文字が表示されれば OK です。

vue_5-5-6.png

3-4. 変数とメソッドを追加する

それでは、SetupTest.vue コンポーネントに「変数」と「メソッド」を追加します。
コードを次のように修正します。

<script setup>
import { ref } from 'vue'

const inputText = ref('')
const reset = () => inputText.value = ''
</script>

<template>
  <input v-model="inputText"/><br />
  <button @click="reset">リセット</button>
  <div>入力した文字: {{ inputText }}</div>
</template>

<style></style>
VSCode の画像を表示

vue_5-5-7.png

① template の修正

template 部分には次のように、v-model を使用した入力ボックス、reset メソッドを実行するボタン、入力文字を表示するマスタッシュ構文を追加しています。

<template>
  <input v-model="inputText"/><br />
  <button @click="reset">リセット</button>
  <div>入力した文字: {{ inputText }}</div>
</template>

実際の画面では次のように表示されます。

vue_5-5-8.png

② script の追加

そして、肝心の script 部分です。
ref 関数のインポートを除けば 2 行のみの記述であり、リアクティブ変数 inputText と、それを初期化する reset メソッドを定義しています。

<script setup>
import { ref } from 'vue'

const inputText = ref('')
const reset = () => inputText.value = ''
</script>

inputText は、テンプレート側の v-model で双方向データバインディングされています。

script setup 構文を使用しない場合は、次のように記述する必要があります。

<script>
import { ref } from 'vue'

export default {
  setup() {
    const inputText = ref('')
    const reset = () => inputText.value = ''

    return {
      inputText,
      reset
    }
  }
}
</script>

比較をすると、script setup 構文のシンプルさがよく分かると思います。

3-5. ブラウザで動作を確認する

ブラウザで動作を確認してみましょう。
ローカルサーバを起動していない場合は npm run dev で起動してください(なお、停止コマンドは ctrl + c です)。

以下のように、適当に文字を入力して双方向データバインディングがされているかを確認します。

vue_5-5-9.png

また「リセット」ボタンを押して reset メソッドを実行してみましょう。
文字がクリアされれば OK です。

script setup 構文内で、算出プロパティおよびウォッチャを使用する方法については、次のチャプターにて見ていきます。

Lesson 5 Chapter 7
算出プロパティ/ウォッチャ

算出プロパティとウォッチャについては、Lesson 3 の Chapter 5 で既に学習しました。
ここでは、復習を兼ねつつ、script setup 構文における算出プロパティとウォッチャの使用方法について見ていきます。

1. 算出プロパティ

1-1. 基本構文

script setup 構文では、算出プロパティも script タグ内の直下に記述します。
Lesson 3 で学習したように、算出プロパティの基本的な構文は次のとおりです。

const [算出プロパティ名] = computed([演算を行うコールバック関数])

1-2. 実際に算出プロパティを追加する

それでは、SetupTest.vue コンポーネントに、算出プロパティを追加していきます。
追加箇所は、下図の赤枠部分となります。

vue_5-7-1.png

全てのコードをテキストで表示
SetupTest.vue
<script setup>
import { ref, computed } from 'vue'

const inputText = ref('')
const reset = () => inputText.value = ''
const getLength = computed(() => inputText.value.length)
</script>

<template>
  <input v-model="inputText"/><br />
  <button @click="reset">リセット</button>
  <div>入力した文字: {{ inputText }}</div>
  <div>現在 {{ getLength }} 文字です</div>
</template>

<style></style>

① template への追加

template 部分には次の 1 行を追加しています。
ここに、入力ボックスに入力した文字列の「文字数」が表示されます。

<div>現在 {{ getLength }} 文字です</div>

② script への追加

script 部分には、次の算出プロパティを追加しています。
入力文字が変更されるたびに、文字列の長さを再計算するものです。

const getLength = computed(() => inputText.value.length)

なお、import 文に computed を追加する必要があります。

import { ref, computed } from 'vue'

③ ブラウザで動作確認をする

ブラウザで動作を確認してみましょう。
入力ボックスに、適当な文字を入力してください。

vue_5-7-2.png

算出プロパティが正しく定義されていれば、文字を入力するたびに、文字数の表示が変化していることが確認できます。

2. ウォッチャ

2-1. 基本構文

今までと同様に script setup 構文では、ウォッチャも script タグ内の直下に記述します。
Lesson 3 で学習しましたが、ウォッチャには 2 種類の関数が用意されています。
それぞれの基本構文は次のとおりです。

① watchEffect の基本構文

watchEffect(コールバック関数)

② watch の基本構文

watch(
  リアクティブ変数名,
  (変更後の値, 変更前の値) => {
    演算内容
  }
)

2-2. 実際にウォッチャを追加する

ここでは、watchEffect を使用します。
下図のように SetupTest.vue コンポーネントの script タグ内に追記していきます。

vue_5-7-3.png

全てのコードをテキストで表示
SetupTest.vue
<script setup>
import { ref, computed, watchEffect } from 'vue'

const inputText = ref('')
const reset = () => inputText.value = ''
const getLength = computed(() => inputText.value.length)
watchEffect(() => {
  if (getLength.value > 5) {
    alert('入力できる文字数は 5 文字までです')
    inputText.value = inputText.value.slice(0, 5)
  }
})
</script>

<template>
  <input v-model="inputText"/><br />
  <button @click="reset">リセット</button>
  <div>入力した文字: {{ inputText }}</div>
  <div>現在 {{ getLength }} 文字です</div>
</template>

<style></style>

① script への追加

script 部分には、次のように watchEffect を追加しています。

watchEffect(() => {
  if (getLength.value > 5) {
    alert('入力できる文字数は 5 文字までです')
    inputText.value = inputText.value.slice(0, 5)
  }
})

getLength および inputText の 2 つの変数を監視しており、入力文字数が 5 文字を超えたときに alert を表示するようにしています。 また、alert の表示後は、inputText の値を前方から 5 文字分のみに変更するようにしています。

なお、import 文に watchEffect を追加する必要があります。

import { ref, computed, watchEffect } from 'vue''

② ブラウザで動作確認をする

ブラウザで動作を確認してみましょう。
入力ボックスに文字を入力して 6 文字以上となるようにしてください。

vue_5-7-4.png

5 文字を超えると watchEffect に設定した alert が実行されます。
OK ボタンを押して閉じると、入力欄およびマスタッシュタグ部分にも 6 文字目以降の文字は表示されません。

script setup 構文における算出プロパティとウォッチャの使い方は以上です。
setup() 関数内に記述する場合と大きな違いがないことが確認できたと思います。

Lesson 5 Chapter 8
DOM の直接参照(ref 属性)

ここでは、HTML 内の要素(ノード)を直接指定して、その値(オブジェクト)を取得する方法について見ていきます。

一般的な JavaScript であれば id 名などを使用して、次のような構文で要素の値を取得することができます。

const element = document.getElementById(id);

Vue では ref 属性を使用することで要素の値(オブジェクト)を簡単に取得することができます。
ref 属性については、Lesson 3 の Chapter 6 でも簡単に紹介しましたが、このチャプターでは、script setup 構文を使用しつつ、詳しく見ていきます。

1. ref 属性の基本構文

ref 属性を使用することで、テンプレートの DOM 要素の参照を取得することができます。
基本的な書き方は次のとおりです。

<script setup>
  import { ref } from 'vue'
  const element = ref()
</script>

<template>
  <div ref="element">こんにちは</div>
</template>

① template 側の指定

ref 属性は ref="element" という形で、次のように指定します。
element は名称なので何でも構いません。

<div ref="element">こんにちは</div>

② script 側の指定

script 側(script setup 構文)では、次のように定義します。
Lesson 3 では初期値を null としていましたが、ここでは ref() というように何も指定しません(この場合、初期値は undfined となります)。

const element = ref()

以上の記述をすることで、リアクティブ変数 element に「指定した DOM 要素の参照」を取得することができます。

2. ref 属性を使用した具体例

それでは、実際に ref 関数を記述してみましょう。

2-1. RefTest.vue ファイルを追加する

src/components ディレクトリに、以下のように RefTest.vue ファイルを追加します。

vue_5-8-1.png

作成した RefTest.vue ファイルには、次の内容を記載します。

<script setup>
  import { ref, onMounted } from 'vue'
  const element = ref()
  onMounted(() => console.log(element.value))
</script>

<template>
  <div ref="element">こんにちは</div>
</template>

内容は、先ほどの基本構文とほぼ同じですが、要素の値(オブジェクト)が取得できたかを確認するために、次の 1 行を追加しています。

onMounted(() => console.log(element.value))

onMounted() 関数を使用して、アプリケーションインスタンスがマウントされてから、取得した要素の値を出力するようにしています。

2-2. App.vue ファイルに子コンポーネントとして追加する

続いて、RefTest.vueApp.vue の子コンポーネントとして追加するために、App.vue ファイルを次のように修正します。

vue_5-8-2.png

全てのコードを表示
App.vue
<script setup>
// import HelloWorld from './components/HelloWorld.vue'
// import SetupTest from './components/SetupTest.vue'
import RefTest from './components/RefTest.vue'
</script>

<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <!-- <HelloWorld msg="Vite + Vue" /> -->
  <!-- <SetupTest /> -->
  <RefTest />
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

① script の修正

SetupTest.vue のインポート部分はコメントアウトしておきます。
その次の行に、RefTest.vue のインポート文を追加します。

// import SetupTest from './components/SetupTest.vue'
import RefTest from './components/RefTest.vue'

② template の修正

SetupTest コンポーネントの挿入部分をコメントアウトします。
その次の行に、RefTest コンポーネントを挿入するために <RefTest /> を追記します。

  <!-- <SetupTest /> -->
  <RefTest />

<RefTest /> の記述部分は <RefTest></RefTest> としても OK です。

2-3. ブラウザで動作確認をする

それでは、ブラウザで開いて動作確認をしてみましょう。
ターミナルを開き、コマンド npm run dev を打って、アプリケーションを起動します。

ブラウザの開発者用画面を開き Console タブを開いてください。

vue_5-8-3.png

ref 属性の設定が正しくできていれば、以上のように、指定したノードの HTML を取得することができます。

以上、本レッスンでは、Vite を使用した Vue プロジェクトについて学んできました。
script setup 構文など重要な内容も出てきていますので、分からなくなったら読み返しつつ、理解を深めていただければと思います。