Vue3がリリースされ、
Vue.jsは大きく変わりました。
本記事では、Vue.jsの中でも、
この大きく変化したVu3に焦点を当てて解説します。
環境構築として、
Dockerを使い、TypeScriptと、
Vue.js界隈では有名な、UIフレームワークの、
Vuetifyも導入します。
上記の環境構築に加え、Componentなどといった、
フロントエンドの基本用語の解説、
テンプレート構文などのVue.jsの文法、
Vue.jsの起動の仕組みについてまで解説します。
文字ではなく、動画で学習したい方は、
下記を御覧ください。
また、Vue3全般について、
フル動画もございますので、
動画一本でVue3をマスターしたい方は、
こちらを御覧ください。
Vue.js概要
Vue.jsとは、Javascriptフレームワークの一種です。
昨今の開発では、実質Vue.jsとReactの二択になっている気がしますが、
よく言われるのは、VueはReactよりも学習コストが低いという点です。
(真偽は定かではありませんが。)
確かに、Vue.jsは、
Reactよりもとっつきやすい印象があり、
デザイナーの方なども、VueとReactなら、
Vueの方が良いという方は一定数いました。
Reactは、やや関数型言語のような記法のため、
書き方がやや難解になりやすいというのもあるのかもしれません。
そのため、Vue.jsは今でも人気のある
フレームワークの一つです。
そんなVue.jsですが、Vue2とVue3では、
書き方や構成などがかなり大きく変わりました。
Vue2で広く使われていたライブラリが、
Vue3ではあまり採用されなくなったり、
文法なども変わりました。(ここでは、options api → composition apiへの
デファクトスタンダードの変化について念頭においています)
そのため、その大きな変更や、
未だVue3に対応していないライブラリがあることなどに、
戸惑っている方もいるかと思います。
ただ、基本的には、Vue3への変更は良い変更とみなしていいものでして、
Vue3になって、TypeScriptのサポートが強力になり、
Composition ApiというReactに似たような(?)
書き方が主流になったので、
Options Apiの弱点であった、処理が散らばった書き方というものを
克服できるようになりました。
https://ja.vuejs.org/guide/extras/composition-api-faq.html#will-options-api-be-deprecated
なので、個人的な印象としては、
Vue3 CompositionAPIの構成であれば、
Reactと遜色はあまりないと感じています。
(ライブラリ等の対応状況は懸念点ではありますが、
やがて対応されて、技術的に枯れることを信じて)
そのため今からVue.jsを学ぶことは、
十分有意義なことだと思います。
Vue.jsについては、案件数も多く、
使用している企業も多いので、
その点でもそこまで心配はいらないと思います。
Vue3ハンズオン
概要はこれぐらいにして、
実際にコードを書いてみましょう。
Vue3の強みは、何と言っても、
Composition apiとTypeScriptサポートにあるので、
本記事でもこの2つを採用していきます。
Docker環境の構築
今回はRailsプロジェクトと同じディレクトリ構成として、
下記のようにします。
Railsの環境構築手順自体は、
こちらで解説しています。
-
参考【Ruby on Rails7環境構築】Dockerでrails newする
rails newとは? rails newとは、文字通り、新しいrailsアプリケーションを作成するコマンドです。 rails new | Railsドキュメント (railsdoc.com) 本記 ...
続きを見る
また、下記ではDockerを使っていきますので、
Dockerの基礎知識に不安がある方は、下記の記事を御覧ください。
-
参考Dockerとは何か?概要を完全解説 簡単なWebサーバー構築で基礎を学ぶ
Dockerとは? Dockerは、コンテナ型仮想環境を作成するソフトウェアの一種で、隔離された実行環境を用意することが特徴です。 https://aws.amazon.com/jp/docker/ ...
続きを見る
まずは、docker-compose.ymlファイルです。
version: '3.9'
services:
db:
image: postgres
volumes:
- ./api/tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
front:
build: .
working_dir: /app
volumes:
- .:/app
ports:
- "5173:5173"
api:
build: ./api
command: bash -c "rm -f api/tmp/pids/server.pid && bundle exec rails s -p 4000 -b '0.0.0.0'"
stdin_open: true
tty: true
volumes:
- ./api:/myapp
ports:
- "4000:4000"
depends_on:
- db
ここでは、apiにRailsを使い、
dbにpostgre sqlを使用しています。
この2つのコンテナ構築については、
上記のRuby on Rails環境構築のものを、
基本そのまま使用していますので、
新しいコンテナは、frontになります。
portは5173にし、workdirは、/appにします。
Dockerfileは下記のような感じです。
FROM node:18-slim
WORKDIR /app
RUN apt-get update
node18系を採用しました。
imageの種類としては、slimを使いました。
あとは、特にこれといった特徴がない、
簡素なコンテナです。
一旦、構成はこのようなシンプルな感じでいきます。
記載したら、buildしましょう。
docker compose build
その後、コンテナを立ち上げます。
起動終了した後に無駄にコンテナ残したくないので、
--rmオプションも付けまして、npm init vue@latestします。
docker compose run --rm front npm init vue@latest
これで新規プロジェクトを作成できます。
プロジェクト名は、frontとし、
これで作成すると、ルートにfrontというディレクトリが作成されます。
さて、ここでDockerfileを修正します。
場所もfrontディレクトリ直下に移動します。
FROM node:18-slim
WORKDIR /app
COPY . /app
RUN apt-get update
COPYの命令を付け加えました。
docker-compose.ymlも修正します。
version: '3.9'
services:
db:
image: postgres
volumes:
- ./api/tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
front:
build: ./front
working_dir: /app
volumes:
- ./front:/app
ports:
- "5173:5173"
api:
build: ./api
command: bash -c "rm -f api/tmp/pids/server.pid && bundle exec rails s -p 4000 -b '0.0.0.0'"
stdin_open: true
tty: true
volumes:
- ./api:/myapp
ports:
- "4000:4000"
depends_on:
- db
volumesの設定を付け加え、
buildのディレクトリ階層を加えます。
もう一度、buildします。
docker compose build
yarn installも走らせます。
docker compose run --rm front yarn install
くどいですが、
もう一度Dockerfileを修正します。
CMDを加えます。
FROM node:18-slim
WORKDIR /app
COPY . /app
RUN apt-get update
CMD ["yarn", "dev", "--host"]
ここまで来たら、
あとは下記で立ち上げます。
docker compose build
docker compose up -d
createApp関数
さて、環境構築が終わったので、
簡単にVue.jsの起動の仕組みを解説します。
Vue.jsの場合、
createApp関数で、アプリケーションのインスタンスを開始しています。
https://ja.vuejs.org/guide/essentials/application.html
作成されたばかりだと、
このように設定されているかと思います。
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import './assets/main.css'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
vueからcreateAppをimportして、
App.vueをcreateAppの引数に渡しています。
このApp.vueとは何でしょうか?
その前に、フロントエンドの基本用語である、
Componentについて解説します。(App.vueもComponentです)
Componentとは?
Componentとは、webパーツの構成パーツのことを指します。
平たく言うと、部品です。
例えば、よくあるWebサイトなどに、
ログインボタンなどがあると思います。
あれも、いわばログインボタンComponentのようにみなすこともできます。
あとは、よくあるお問い合わせフォームなんかも、
Componentといえるでしょう。
これらは、再利用性が特徴で、
様々な場所でComponentを呼び出すことで、
共通化することができます。(いわば共通化の手段ですね)
Component、すなわち部品をどの程度の大きさで分割するかは、
開発者によって、異なるので一概には言えませんが、
例えば下記の画像だと、
右側にある、Content1とかContent2とかは、
カード形式のコンポネントとみなすことができそうですね。
また、そうした小さいコンポネントをひとまとめにして、
Contentカードが4つあるコンポネントとみなすこともできます。
なので、Componentとは、
再利用が可能な部品のことですね。
ちなみに、このようなCompoent設計には、
Atomic Designという有名な思想がありますので、
興味がある方は調べてみてください。
mount
さて、createAppに戻りますが、
createAppに渡しているのは、コンポーネント(App.vue)ですね。
コンポネントは、他のコンポーネントを子要素として保持できるのですが、
App.vueは、そのようなルートコンポネントの役割を果たしています。
そのため、この場合、
デフォルトで作成されている、
App.vueがルートコンポーネントになります。
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<header>
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />
<div class="wrapper">
<HelloWorld msg="You did it!" />
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
</nav>
</div>
</header>
<RouterView />
</template>
Vue.jsの場合、
Compoentは、一つのVueファイルにまとめることが穂とんです。
App.vueの中身を見ますと、この中で、
HelloWorld.vueのコンポーネントがインポートされているので、
これは子コンポーネントになります。
このように、コンポーネントからコンポーネントを呼び出していって、
アプリケーションが構成されていくイメージですね。
ただ、こうした要素を画面にレンダリングするには、
mount(紐づけのようなイメージ)する必要があります。
app.mount('#app')
#appは、id=appですが、
この要素は、
<!DOCTYPE html>
<html lang="en">
<head>
中略
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
の<div id="app">の部分にあります。
そのため、この部分にapp.vueのHTMLが
挿入されていくようなイメージですね。
先程説明した、
App.vueとかHelloWorld.vueみたいなコンポネントは、
この<div>タグ内に表示される仕組みになっており、
そのようにレンダリングさせる実装が、mountといった感じです。
つまり、createAppから、最終的に、
#appの部分にmountされるという流れになっている感じです。
テンプレート構文
テンプレート構文とは、
その内部を、Javascriptのコードにしてくれるものです。
https://ja.vuejs.org/guide/essentials/template-syntax.html
ドキュメントにも書かれていますが、
やや説明が難しいですよね。
要は、vueファイルのhtmlの部分に、
<template>
<div class="wrapper">
{{ ここにJavascriptのコードを実行できる }}
</div>
</template>
というふうに、
{{ }} のマスタッシュ構文というものを使って、
その中にJavaScriptのコードを埋め込むことができます。
ただ、挿入できるのは式に限られるので、
if文とか、変数代入みたいな、文を実行することはできません。
なので、かわりに三項演算子を使います。
{{ Boolean('test') ? 1 + 3 : 23 * 4 }}
このような感じで、JSのコードを入れることができます。
この場合、三項演算子でtrueになるので、
1 + 3で4が表示されます。
JavaScript/TypeScriptの基本文法については、
下記の記事で紹介しているので、
ご参考ください。
-
参考【TypeScriptの変数】let/constと変数として使えないもの
TS Playground TS Playgroundは、TypeScriptを試すことができるサンドバッグ的環境。 通常、プログラミング言語の学習などをする際は、自分のPCに実行環境を構築する必要が ...
続きを見る
ただ、上記のようなやや複雑な処理を
何でもかんでもテンプレート構文に詰め込むのは、
コードが肥大化してメンテナンス性が下がるので、
あまり良くはありません。
この場合、算出プロパティを使うのがいいでしょう。
算出プロパティについては、こちらの記事で解説しています。
-
参考【Vue3】リアクティブとは?refやcomputed(算出プロパティ)
本記事では、Vue.jsの重要な概念である、リアクティブについて扱います。 その中でも、refやcomputedについて、詳細に解説します。 動画でご覧になりたい方は、こちらをご参考ください。 htt ...
続きを見る
Vuetifyインストール
Vuetifyとは、Vue2でのデファクトスタンダードだった、
UIフレームワークのことです。
Vue3の場合、必ずしもVuetifyがデファクトというわけでもなくなりましたが、
使いやすいので、本記事ではVuetifyを採用します。
(※Vue3だとVuetifyのドキュメントは一部整備中だったりするので、
企業などでの技術選定は慎重になったほうが良いかもしれません)
導入方法としては、
まず、yarnをインストールします。
npm install --global yarn
yarnを入れたら、
下記でプロジェクトを作成してくれます。
yarn create vuetify
https://vuetifyjs.com/en/getting-started/installation/
UIフレームワークで、プロジェクトを作成してくれるのは、
なかなかに感動ものですよね。
ただ、おそらく大抵の場合、
既存のVueプロジェクトにインストールすることになると思うので、
実際は、下記のようなコマンドを実行することになるでしょう。
yarn add vuetify@^3.1.11
導入したら、
あとはmain.tsをvuetifyを入れるよう書き換えます。
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import './assets/main.css'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
const vuetify = createVuetify({
components,
directives,
})
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(vuetify)
app.mount('#app')
これでvuetifyを使うことができます。
-
あわせて読みたいVue.jsとChatGPT APIでずんだもんに回答を喋ってもらう
ChatGPTとは? ChatGPTとは何でしょうか?本人に聞いてみました。 おお、模範解答(?)ですね。 このように、ChatGPTとは、AIの一種で、人間が質問したものに対して、応答してくれます。 ...
続きを見る
-
あわせて読みたい【Vue3/v-model】双方向データバインディングとは?
Vue.jsの概念に、双方向データバインディングというものがあります。 これは、単方向データバインディングに対するものです。 本記事では、双方向データバインディングの解説を通して、単方向データバインデ ...
続きを見る
-
あわせて読みたい【Vue3】リアクティブとは?refやcomputed(算出プロパティ)
本記事では、Vue.jsの重要な概念である、リアクティブについて扱います。 その中でも、refやcomputedについて、詳細に解説します。 動画でご覧になりたい方は、こちらをご参考ください。 htt ...
続きを見る
-
あわせて読みたい【Vue3条件分岐ループ】v-if/v-showやv-forのkey
本記事では、Vue3におけるv-ifやv-forの使い方、v-showとの違い、v-forのアンチパターンについて紹介します。 Vue.jsでは、普通のプラグラミング言語のように、v-ifなどのような ...
続きを見る
-
あわせて読みたい【Vue3ライフサイクルフック】onMountedって何?関数の順序と概念
Vue3には、コンポーネントのライフサイクルに関わるさまざまなフックが用意されています。 これらのフックを適切に使うことで、コンポーネントの初期化、更新、削除などのタイミングで、カスタムコードを実行す ...
続きを見る
-
あわせて読みたい【Vue3 props/emit】コンポーネント間通信
コンポーネントとは? コンポーネントとは、そのままの意味としては、部品とか、構成要素とかといったものがあります。 Vue.jsにおけるコンポーネントという概念も、大まかにはそのような意味で、より具体的 ...
続きを見る