浦島太郎のVue.js

# 前書き

数年ぶりにJavaScript触ったら結構変わってるな…！
と思ったので、私みたいな浦島太郎さんが他にもいたら役立てて欲しいなという記事です。
一応Vue3の想定で書いていますが、Vue2限定のものが混ざっていたらすみません。

## 想定読者層

だいたい下記レベル感を想定しています。

- 他の言語でプログラミング自体はできる
- 基礎的なLinuxコマンドが打ててアレルギーがない
- JavaScriptは昔ちょっとjQuery触ったことがある（一応DOMの概念はわかる）
- ブラウザ上で動くJavaScriptについては一応知ってる
- 最近イケてると噂のVue.jsを触ってみたい
- npmってなにさ？
- webpackってなにさ？
- 細かい部分はググればわかりそうだけど、前段階としてざっくり概念を知ったり、できることを簡単に知っておきたい

## 注意書き

私も学習しながらざっくり理解で進めたので、正確でない部分があるかもしれませんがご了承ください。
間違いがあれば教えて頂けると助かります。

# Vue.jsってどういうもの？

そもそも問題ない人は[公式](https://jp.vuejs.org/index.html)を読んでもらうのが一番良いと思います。
というより問題なく読める人はここまでで回れ右してもらって大丈夫です。

しかし

> 公式ガイドは、HTML、CSS そして JavaScript の中レベルのフロントエンドの知識を前提にしています。フロントエンドの開発が初めてであるならば、最初のステップとして、フレームワークに直接入門するのは良いアイデアではないかもしれません。基礎を学んで戻ってきましょう！他のフレームワークでの以前の経験は役に立ちますが、必須ではありません。

こんなことが書いてあって、浦島太郎な私には敷居が高かったです。
実際一度読んだだけではわからないことも多々ありました。

私が現在理解している範囲でVue.jsでできることを簡単に書くと

- 任意の範囲のDOM定義をvueコンポーネントとして分割して定義しておける
- コンポーネントを呼び出す際には引数を与えることができ、それによって描画内容に幅を持たせられる
- 複数のコンポーネントを組み合わせて画面を構築していくことができる
- SPA（Single Page Application）やSSR（Server Side Rendering）を構築できる

という感じのようです。

## Vue.jsってどうやって動いているの？

基本的なことですが、jQuery脳から入るとこの時点で少し疑問符が湧くので、理解を進めるため簡単に書いておきます。

1. 表示されるWebページ（index.html）はファイルとして普通に用意されており、ユーザーはここにアクセスする
1. index.html内にjsタグを埋め込んでおき、Vue.jsで作成され1ファイルに圧縮されたjsファイル（main.js）を読み込み、実行する。
1. main.jsではVueのアプリケーション・オブジェクトが作成され、ここでコンポーネントを読み込み、Vueで定義したDOMの描画を行う

# JavaScript初心者が躓きがちな記法や概念

JavaScriptには他の言語に慣れているとパッとわからない書き方や概念がいくつかあります。
そして、ググってもこのあたりの知識は前提として記事が書かれており、ググり方もよくわからず困ったりしました。
なので基礎知識として、よく見るなと思ったものについて最初に軽く触れておこうと思います。

## ES2015（別名ES6）

ECMAScriptの6th Edition、2015年に策定されたためES2015と呼ばれたりES6と呼ばれたりするようです。
現状最新のJavaScriptの言語仕様の名前、と覚えておけば概ね問題ないと思います。
JavaScriptはブラウザによって挙動が微妙に異なる部分があり、それでは困るため、共通仕様として決められたもののようです。

## アロー関数

アローを使うことで、methodとかfuncとかのそれらしい英字なしに関数を定義することができます。

```js
// 従来だとこう書く
var fn = function (a, b) {
  return a + b;
};

// アローで書く
const fn2 = (a, b) => {
  return a + b;
};

// 単一式の場合は色々省略できる
const fn3 = (a, b) => a + b;

// オブジェクトを返却する場合は少し書き方が変わる
const fn4 = (a, b) => ({ sum: a + b });
```

## スプレッド構文

これは他の言語にもあったりなかったり。
可変長で引数を受けたり渡したりできます。

```js
function func (...r) {
  console.log(r[1])
}

func(1, 2, 3, 4, 5); // => 2
```

通常の引数と併用も可能です

```js
function func (a, ...r) {
  console.log(r[1])
}

func(1, 2, 3, 4, 5); // => 3
```

渡す時も同様です

```js
function func (a, b, c) {
  console.log(a + b + c)
}

const arr = [1, 3, 5]
func(...arr); // 9
```

配列の中に展開も可能です

```js
const arr1 = [1, 2, 3]
const arr2 = [...arr1, 4, 5, 6]

console.log(arr2); // [1, 2, 3, 4, 5, 6]
```

## オブジェクト

リテラルだと以下

```js
a = {
  key1: value1,
  key2: value2,
}
```

オブジェクトのKeyValueのことはプロパティと呼びます。
プロパティにはドット区切りでも辞書形式でもアクセス可能です。
ドット区切りを使う方が一般的らしいですね。

```
a.key1 == a["key1"] == "value1"
```

オブジェクトに関数の定義を入れる場合は省略記法があります。

```
let rgb = {
  r: 255,
  g: 128,
  b: 64,
  total1() {
    return this.r + this.g + this.b
  },
  total2: function() {
    return this.r + this.g + this.b
  },
  total3: () => {
    return this.r + this.g + this.b
  },
}
```

## クラス定義

constructor() は言語側で予約済。
Vue.jsを使う上ではあまり必要ないかもしれませんが、念の為。

```js
class Hoge {
  constructor(args) {
    this.args = args
    // initial
  }

  method () {
    ...
  }
}
```

# node.jsについて最低限

node.jsってサーバーサイドjsのことじゃなかったっけ？
たしかシングルスレッドで非常にレスポンスが早いけど設計に注意が必要なWebサーバーだったような…
などと浦島さんは思いました。

どうもnode.jsが示す範囲はもう少し広いようでした。
フロントのWebページ用のjsコードであっても開発中はnode.jsで管理して作成し、完成したコードをコンパイルして最終的にはフロントで使う、という開発手順になっているみたいですね。

2021/11/16追記：node.jsについては[こちら](https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb)の記事が非常にわかりやすかったです。node.jsはPC上でのJavaScript実行環境、というのはとてもしっくりきました。

## npmとは

簡単に書くと、JavaScriptのライブラリ等を管理するためのツール。
PHPでいうcomposerだったり、Pythonでいうpipやpoetryに近い概念だと思っておけばとりあえず大丈夫だと思います。

package.jsonの中に必要なライブラリのバージョンや、パッケージの名前、製作者や連絡先などの情報を入れておけます。
場合によっては利用するライブラリのオプション指定などもこのファイル内に書いておくケースもあるようです。

また、実行コマンドをpackage.jsonの中に定義しておいて、呼び出すこともできます。
よく使うビルドコマンドなどをオプション付きで書いておいて使う、などが主な用途になると思います。

```json:package.json
{
  "name": "hoge",
  "version": "0.0.1",
  ...
  "scripts": {
    "dev": "コマンド"
    npm run ***で実行したいコマンドを定義しておく
  },
  "dependencies": {
    実行に使うライブラリとバージョンの一覧。jqueryやvueなどを指定する。
  },
  "devDependencies": {
    開発中のみ使うライブラリ。babel、eslint、webpackなどを指定する。
  }
}
```

```sh
# dependenciesとdevDependenciesに定義しておいたライブラリをnode_modules以下にインストールする
npm install

# package.jsonのdevで定義しておいたコマンドを実行
npm run dev
```

このあたりについて解説するとそれだけで1本書けるので、ここでは割愛します。

## webpackとは

大量のJavaScriptを書いてWeb上で使用したい場合、開発者としてはある程度の単位でファイルを分けて管理したいです。
しかし、ファイルが増えるたびにそれを読み込む定義をhtml側に逐一追加していくのは非常に大変で、何よりアホらしいですよね。
こんな課題を見事に解決してくれるのがwebpackです。
複数のjsファイルや、sassや画像までもまとめ上げ、1ファイルに出力してくれます。
html側はまとめ上げた後の1ファイルだけを常に読み込むよう指定しておけば、js側の開発過程でファイルがどう増減しようが関係ないわけです。素晴らしい。

なお身近な範囲ではwebpackを使っている人が多かっただけで、複数ファイルを1ファイルにまとめ上げる方法は他にもあるそうです。
興味があれば探してみてもいいと思います。

# Vue.jsについて

Getting started的なものは公式にお任せするとして、ここでは学習前にざっと頭出ししたりする用のリストとして書いていきます。

## .vueファイルに含まれるもの

大きく3種類、基本的には2個です。

1. `<template>` DOM要素
1. `<script>` JavaScriptコード
1. `<style>` CSS

### template

HTMLタグを基本として、vue特有の記法やjs変数の埋め込みをしながらDOMを定義していきます。

template配下のトップレベルにはタグを1つしか指定できないため、そうできる単位でコンポーネントを切り分けることを意識しましょう。

```vue:NG
<template>
  <div>
    ...
  </div>
  <div>
    ...
  </div>
</template>
```

```vue:OK
<template>
  <div>
    <div>
      ...
    </div>
    <div>
      ...
    </div>
  </div>
</template>
```

#### v-xxx

v-から始まる属性は、およそ何らかの方向性で変数をDOMに紐付けるための指定方法となっているようです。

##### v-html

変数を直接HTMLとして使いたい場合に用いる。

```vue
<div v-html="editableHtml"></div>
```

##### v-bind

タグの属性値に変数を使いたい場合に使う。

```vue
<div v-bind:name="hoge"></div>
```

これはname属性に変数hogeの値を指定した形になる。
なおv-bindは省略可能、というか省略することの方が多いらしいです。

```vue
<div :name="hoge"></div>
```

###### オブジェクト構文

v-bindに辞書を指定し、辞書の値がtrueなら有効、falseなら無効として指定できます。
わかりやすい例としてはclass指定です。

```vue
<div :class="{ red: true, blue: false }">hoge</div>
```

##### v-if

ifの中身が真なら描画する。v-elseもあります。
これはわかりやすいので例は省略します。

##### v-for

forループ。v-ifとは同時に指定できないようです。

```vue
<template v-for="i in 10">
```
```vue
<template v-for="item in array">
```
```vue
<template v-for="(item, index) in array">
```
```vue
<template v-for="(value, key) in object">
```

##### v-on

クリック等のなんらかの条件で発火するイベントを処理したい場合に指定します。
methodsの中に定義したメソッドを指定して呼び出します。

例えばonclickならv-on:clickとして指定します。

```vue
<p v-on:click="doAction">...</p>
```

省略して@で書く方が一般的らしいです。

```vue
<p @click="doAction">...</p>
```

#### ref属性

idやcssセレクタなどはビルド時に変換されてしまい想定通りの挙動にならない可能性があるため、特定のdomに対して何かしたい場合にはrefを使うことができます。
直接HTML要素に介入するため想定外の挙動を起こす可能性があり、利用は最小限にした方が良いそうです。

```vue
<p ref="hoge">
```

```vue
this.$refs.hoge
```

#### templateタグ

templateタグ自体は描画されません。
v-forやv-ifなどで一定の範囲を括りたい時などに有用です。

#### transitionタグ

trasitionタグ自体は描画されません。
描画時や消滅時にcssを定義しておけるもの、らしいです。

### script

コンポーネントごとのjs部分を定義します。
だいたい以下2種類を記述することが多いけど、他にも色々と書く必要があるケースもあります。

1. `import`
1. `export default`

#### import

外部や別ファイルに定義してあるモジュール、コンポーネントをインポートして、このコンポーネント内で使えるようにします。

```vue
import AAA from 'XXX'
import { A, B, C } from 'YYY'
import D from '@path/to/module'
```

#### export default

最初にこれを見た時に私は「export defaultってなんぞ？」と結構謎でしたが、これは外部からモジュールとして呼ばれた時にデフォルトで参照するものを指定しているそうです。
これ自体はVueでなくJSの記法らしいですね。
よくわからなければ「おまじない」と思っておいても問題ないと思います。

Vue.jsではだいたい以下のような形でオブジェクトを定義していくことが多いと思います。

```vue
export default {
  ...
}
```

##### components

importして利用するコンポーネントを指定しておきます。

```
export default {
  components: { A, B },
}
```

指定したコンポーネントはタグのようにしてtemplate内で使用でき、引数を渡すことも可能です。

<A :args="hoge"></A>

##### props

モジュールとして外部から呼ばれた際に受け取れる引数について定義できます。

```
export default {
  props: {
    hoge: String,
    xyz: {
      type: Number,
      default: 0,
    },
    percentage: {
      type: Number,
      required: true,
      validator: (value) => {
        return value == parseInt(value) && value >= 0 && value <= 100
      },
    },
    f: {
      type: Function,
      required: true,
    }
  }
}
```

##### data

コンポーネントが使う変数を定義できます。

##### computed

算術プロパティを定義できます。
概ねdataやpropsと同様に扱うことができます。
値は依存先の変数が更新された際に再計算されます。

直接関数を定義するとGetterとして扱われますが、Setterも定義できます。

```
computed: {
  calcProperty: function() {
    ... calc process
    return value
  },
  canSetProperty: {
    get() {
      ... getter process
      return value
    },
    set(val) {
      ... setter process
    }
  },
},
```

##### watch

常に値の変更を監視する旨について定義しておけます。
1つの値の影響範囲が広かったりする場合に使うことがあるけど、基本的にはcomputedで簡素に書けることが多そうです。

```vue
watch: {
  propertyName (newValue, oldValue) {
    ... process
  },
}
```

##### methods

関数を定義しておけます。
v-onなどから呼び出すことが多い印象ですが、様々な使い道がありそうです。

##### created

コンポーネントのオブジェクトが作成された直後、propsやdataの設定より後に実行される。
ローカルストレージから値を取り出したり、色々できそうですね。

## よく聞くライブラリ

有名どころについて少し。

### Vuex

様々なコンポーネントで共通して扱える、ストアと呼ばれる保管場所を用意できるライブラリ。
グローバル変数のようなものになるため、大きいアプリケーションになってくると扱いが難しくなりそうですね。

`$store`というグローバルに使用できる値が用意され、そこから値を扱う形になります。

### i18n

複数言語対応を簡単にしてくれるライブラリ。
`$t`というグローバルに使用できる値が用意され、そこから予め定義しておいた文字列を呼び出して描画に用いるような使い方になる。

多言語対応しない場合でも文言を各vueファイルに散らばらせずに一箇所で管理できるため、採用価値は高そうです。

ライブラリが用意する便利変数は頭に大体`$`がついているのかもしれませんね。

# プラスαで知っておくと便利な概念

記事を漁っていると時々でてきて、なんだそりゃ？とならないための予習用です。
ググるにも知識が要りますよね。JS関係では特に苦労しました。

## Flux

Facebookの提唱するWebアプリケーションを開発する際に用いるアプリケーションアーキテクチャです。
アプリケーションをView、Store、Dispatcher、Actionの4部品に分けて扱います。
詳しくは公式へどうぞ。

個人的にはまだ有用性を咀嚼できていませんが、たぶん巨大なアプリケーションになってくると有用性が出てくるのだと想像しています。

## Atomic Design

Vueコンポーネントの設計手法の1つです。
Vueにも一応公式のスタイルガイドがありますが、Atomic Designではコンポーネントの分割単位について細かく定義しています。
コンポーネントを分ける単位に悩んだら参考にすると良さそうです。

# 最後に

フロントの技術推移は早いとは噂で聞いていましたが、実際もう基礎知識がない状態に近いなと感じました。
推移の早さのせいか、検索してもサンプルコードが動かないケースもそれなり。
ともあれ久しぶりにJS触って色々と書いたのは楽しかったです。そのうち個人サイト作る過程とかも記事にしてみたいですね。