【Vue.js3】Vue.jsの基本を理解したい

# :eyes: Vue.js
https://ja.vuejs.org/guide/introduction.html#what-is-vue
> Vue (発音は /vjuː/、view と同様) は、ユーザーインターフェースの構築のための JavaScript フレームワークです。標準的な HTML、CSS、JavaScript を土台とする、コンポーネントベースの宣言的なプログラミングモデルを提供します。シンプルなものから複雑なものまで、ユーザーインターフェースの開発を効率的に支えるフレームワークです。[^1]


Vue.jsの基本をしっかり理解したいので、ざっくりしたところから、少し踏み込んだところまで、この記事にまとめます。

動機は、シンプルに、、業務で使っているからです！

# :chart_with_upwards_trend: JavaScriptフレームワークのトレンド

開始早々少しVue.js自体からは話がそれますが、JavaScriptフレームワークにはどんなものがあるのか調べてみました。

ざっと調べただけでたくさん出てきましたが、以下の12個をピックアップしました。
いくつか聞いたことはありますが、初めましてな名前も多かったです。

| フレームワーク | 概要 | 
| ---------------- | ---- | 
| [React](https://ja.react.dev/blog/2023/03/16/introducing-react-dev)| Facebook社（現Meta社）によって開発され、2015年3月に登場。MVCのViewに特化して、状態を保持するUIコンポーネントを簡単に作成できる。 （厳密にはライブラリ）  | 
| [AngularJS](https://angularjs.org/)        |  Google社により開発された。複数のコンポーネントとしてWebアプリケーションを組み立てるコンポーネント指向で、機能単位で実装を分離が簡単であることや初心者でも扱いやすい。    | 
| [Angular](https://angular.jp/)          |  AngularJSの後継にあたるフレームワーク。AngularJSには描画速度やメモリ・CPUへの負荷など、複数の問題があったため、その改良版としてAngularが開発された。| 
| [Ember.js](https://emberjs.com/)        | 複雑なwebアプリを管理するための機能と、生産性の高く高速化が可能なツールキットが特徴的。データバインディングやコンポーネントなどの機能もある。     | 
| [Svelte](https://svelte.jp/)           | 昨今のフロントエンドフレームワークでは標準で備わっていたと言ってもいい「仮想DOM」の仕組みを備えていない。コードの記述量が少ない。     | 
| [Backbone.js](https://backbonejs.org/)      | 名前のとおり、MVCの骨組みを提供する。実際に実装するにはjQuery、Underscore.jsなどの併用が必須。| 
| [Alpine.js](https://alpinejs.dev/)        |  Vue.jsやReactの持つリアクティブかつ宣言的な性質を、簡単にマークアップに組み込むことができる。ディレクティブなどの基本構文は、Vue.jsを参考にしている。    | 
| [Next.js](https://nextjs.org/)          | Reactをベースに開発された。画像処理に優れている。     | 
| [Nuxt](https://nuxt.com/)             | Vueをベースに開発された。Vueと同様、非常に高速な処理を実現する。     | 
| [Riot.js](https://riot.js.org/ja/)          | カスタムタグを作成することができて、HTML、CSS、JSを1つのタグにまとめることができ、見通しがよい。     | 
| [Hyperapp](https://github.com/jorgebucaran/hyperapp)         | わずか1KBの超軽量フレームワーク。TypeScriptにも対応をしており、ReactやVueをもっと効率よくプログラミングできるように設定されている。     | 
| [jQuery](https://jquery.com/)           | 「できるだけ短いコードで記述する」というコンセプトで開発された。コードが同じであればどのブラウザでも同じ表示・動作を実現してくれる仕様となっている。  | 

そして今、人気のフレームワークは何なのか気になったので、JavaScriptフレームワークのトレンドを調べてみました。

使ったのは、皆さんが一度は訪れたことがあるであろうプログラミング技術に関するQ&Aコミュニティサイト、[Stack Overflow](https://stackoverflow.com/)の*Stack Overflow Trends*という機能です。

https://insights.stackoverflow.com/trends?tags=jquery%2Cangularjs%2Cangular%2Creactjs%2Cvue.js%2Cvuejs3%2Cbackbone.js%2Cknockout.js%2Cember.js%2Cunderscore.js%2Cnext.js%2Cnuxt.js%2Csvelte%2Cvuejs2

質問につけられた、タグの数がグラフになっています。
Stack Overflowが開設された、2008年からのデータです。

jQueryの下降具合とReactの上昇具合が顕著で面白いですね。
2024年3月現在だと、next.jsが上がってきていることも見て取れます。

正直Vue.jsは思ったより少ない印象でしたが、他のフレームワークと比べても、コミュニティの活動が活発で、ドキュメントや、関連する情報、ライブラリも充実しているようなので、質問が少ないのかも？と思ったりもしました。（完全なる憶測です）

では本題に戻って、Vue.jsの特徴からまとめます。

# :mag:Vue.jsの特徴
### 1. 導入ハードル、学習コストの低さ
- Reactもビューに特化した比較的簡単なフレームワーク（ライブラリ）だが、それに比べても簡単
- HTMLベースのテンプレート構文を採用しているため、HTMLとJavaScript（jQuery）に触れたことがあれば直感的に理解できる部分も多い

### 2. アプリの段階的な成長に対応できる（プログレッシブフレームワーク）
https://ja.vuejs.org/guide/introduction.html#the-progressive-framework
- アプリの成長に合わせて機能を追加していける、あるいは、追加のための機能が豊富に用意されている
    - **アプリが拡大してきて、似たような見た目が散在してきた**
        → `コンポーネント`（UI部品を作成するための仕組み）を導入
    - **機能が増えてきたので、より明確にページを分割して整理したい**
        → `Vue Router`という公式ライブラリを加える
    - **より高度に部品化を進めていくと、コンポーネント同士でのデータのやり取りが煩雑になってきた**
        → `Vuex`（アプリで扱うグローバルなデータを中央管理するためのデータベースのような仕組み）を導入

### 3. コンポーネント指向である
- Vue.jsアプリを構成するさまざまな要素の中で、中核となるのがコンポーネント
    - ページを構成するUI部品
    - ビュー（テンプレート）、ロジック（オブジェクト）、スタイルなどから構成される

# :arrow_forward:  Vue.jsアプリを実行してみる
基本的なVue.jsアプリを実行してみます。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="zYeLVGq" data-editable="true" data-user="eebzuttg-the-scripter" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/eebzuttg-the-scripter/pen/zYeLVGq">
  Vue.jsアプリの実行</a> by 廣岡七海 (<a href="https://codepen.io/eebzuttg-the-scripter">@eebzuttg-the-scripter</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- `Vue`クラス
    - Vue.jsの核となる
- `createApp`メソッド
    - アプリケーションインスタンスを作成するためのメソッド
- `mount`メソッド
    - Vueアプリを`id="app"`である要素に紐づけている
- `{ name: value, ...}`
    - ルートコンポーネントの動作オプション
    - dataオプション
        - テンプレート（HTML）から参照できる値を格納したオブジェクトを表す
        - オブジェクトそのものでなく、オブジェクトを返す関数を渡す必要がある
    - アプリで利用する値をデータオブジェクトで用意→テンプレートから参照する、という役割分担が基本
        - このようなデータ割り当ての仕組み
            - **データバインディング**
- `{{...}}`構文（Mustache構文）
    - テンプレートからデータオブジェクトにアクセス
    - 任意のJavaScript式を与えることも可能

# :bulb:ディレクティブ
- テンプレートを構成する仕組み
    - `{{...}}`（Mustache構文）
    - `v-xxxx`ディレクティブ

`{{...}}`は、与えられた式の値をテンプレートに埋め込む基本的な手法。
記法が簡単な分、できることも限られてくる。

属性やスタイルの操作、条件分岐、繰り返し処理など、より複雑な機能を組み込みたい場合は、ディレクティブを利用する。
ディレクティブは、`v-`から始まる属性として表すのが基本。

## v-text
`{{...}}`の代わりに`v-text`ディレクティブを使うこともできる。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="dyajBKe" data-editable="true" data-user="eebzuttg-the-scripter" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/eebzuttg-the-scripter/pen/dyajBKe">
  Untitled</a> by 廣岡七海 (<a href="https://codepen.io/eebzuttg-the-scripter">@eebzuttg-the-scripter</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## v-bind
属性に対して式の値を埋め込みたいとき、`{{...}}`は利用できない。
以下のコードでは、`{{ url }}`にデータが埋め込まれず、正しく動作しない。
```html
<a href="{{ url }}">株式会社日本ピュアシステム 採用サイト</a>
```

属性値の操作には、`v-bind`ディレクティブが利用できる。
`v-bind:属性名="値"`のように表記する。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="BaMOYLR" data-editable="true" data-user="eebzuttg-the-scripter" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/eebzuttg-the-scripter/pen/BaMOYLR">
  Untitled</a> by 廣岡七海 (<a href="https://codepen.io/eebzuttg-the-scripter">@eebzuttg-the-scripter</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### ちなみに
`v-bind`ディレクティブには省略記法もある。
```html
<a :href="url">サイト名</a>
```
# :bulb:算出プロパティ
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="VwgGxLE" data-user="eebzuttg-the-scripter" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/eebzuttg-the-scripter/pen/VwgGxLE">
  Untitled</a> by 廣岡七海 (<a href="https://codepen.io/eebzuttg-the-scripter">@eebzuttg-the-scripter</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- 既存のプロパティを演算（算出）した結果を取得するためのゲッター
- `プロパティ名: 関数, ...`の形式で定義
- `this.プロパティ名`でデータオブジェクト（`email`)にアクセスできる
- 定義済みの算出プロパティをテンプレートから参照するには、データオブジェクトに対するのと同様に、`{{ プロパティ名 }}`とする

## :question: メソッドとの違い
一つ前のコードの`computed`を`methods`に変更すると以下のコードのようになります。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="zYeJRyO" data-editable="true" data-user="eebzuttg-the-scripter" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/eebzuttg-the-scripter/pen/zYeJRyO">
  Untitled</a> by 廣岡七海 (<a href="https://codepen.io/eebzuttg-the-scripter">@eebzuttg-the-scripter</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### 1. 算出プロパティは引数をもてない
- `()`を伴う呼び出しができない
    - 引数を伴うような呼び出しには、メソッドを利用する必要がある

### 2. 算出プロパティは取得用途
- 基本的に、既存データの加工を伴う取得が用途
- メソッドは、データの取得に加えて、操作や更新にも利用できる

### 3. 算出プロパティの値はキャッシュされる
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="wvNEmKE" data-editable="true" data-user="eebzuttg-the-scripter" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/eebzuttg-the-scripter/pen/wvNEmKE">
  Untitled</a> by 廣岡七海 (<a href="https://codepen.io/eebzuttg-the-scripter">@eebzuttg-the-scripter</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- ボタンクリックで、メソッドに紐づいた要素のみ変化する
    - メソッドは、再描画に際して常に実行される
- 算出プロパティは、それが依存するプロパティ（`this.~`で表される値）が変更された場合にのみ実行される
    - 算出プロパティ`randc`は、他のプロパティに依存しないため、初回に呼び出された後は二度と呼び出されない 
    - つまり、もし算出プロパティ`randc`内で、`this.current`を参照するなどしていた場合には、`this.current`が更新されるたびに実行される

# :bulb:ライフサイクルフック
https://ja.vuejs.org/guide/essentials/lifecycle.html#lifecycle-diagram

## :cyclone:ライフサイクル
Vue.jsアプリのインスタンスは、最初に生成された後、要素に紐づけられ、
データの変化に応じてビューを更新させていき、最終的に破棄される。
この一連の流れをライフサイクルという。

## :fishing_pole_and_fish: ライフサイクルフック
ライフサイクルの変化に応じて呼び出される、さまざまなメソッドのこと。

これを利用して、インスタンスの生成から表示、破棄と、決められたタイミングでアプリ独自の処理を割り込ませることができる。

# :thought_balloon: 所感
普段触れてはいつつも、何となくで理解していた部分もあったので、とても良い機会になりました。
引き続き、Vue.jsをラクラク操れる日を夢見て精進していきたいと思います。

# 参考文献
- [Vue.js 公式ドキュメント](https://ja.vuejs.org/)
- [山田祥寛 「これからはじめるVue.js 3実践入門」、SBクリエイティブ株式会社（2022年3月）](https://www.sbcr.jp/product/4815613365/)