[Vue.js] Vue.js 3.x + TypeScript + マテリアルデザイン ことはじめ その2

# これはなに？

[Vue.jsを個人的に始めてみた記録](https://qiita.com/sengoku/items/8f5313214c1159bfe660)の続きです。

ルーティングとVuexについてやっていこうと思います。

# ルーターを追加

Vue CLIを使ってルーターを追加します。

```console
vue add router
```

質問が表示されましたので、以下のように回答しました。

* Use history mode for router? (Requires proper server setup for index fallback in production)
  *  ✅ Yes
  *  No


## ファイルが追加/変更されました

`src/views/About.vue` `src/views/Home.vue` ファイルが追加されました。ルーティング先のコンポーネントになります。

`src/router/index.ts`ファイルが追加されました。このファイルの中でコンポーネントへのルートを設定します。動的にコンポーネントを読み込む設定もできるようです。

```ts
const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "Home",
    component: Home,
  },
  {
    path: "/about",
    name: "About",
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () =>
      import(/* webpackChunkName: "about" */ "../views/About.vue"),
  },
];
```


`src/main.ts` ファイルが変更されました。先で追加された読み込んでいます。

```ts
import router from "./router";

createApp(App)
  .use(router)
  .use(BalmUI)
  .use(BalmUIPlus)
  .mount("#app");
```

# Vuexを追加

Vue CLIを使ってVuexを追加します。

```console
vue add vuex
```

## ファイルが追加/変更されました

`src/store/index.ts`ファイルが追加されました。

中身はないようです。

```ts
export default createStore({
  state: {},
  mutations: {},
  actions: {},
  modules: {},
});
```

`src/main.ts`ファイルが変更されました。
先で追加されたファイルを読み込んでいます。

```ts
import store from "./store";

createApp(App)
  .use(store)
  .use(router)
  .use(BalmUI)
  .use(BalmUIPlus)
  .mount("#app");
```

# これから作るもの

Hello Worldを作ります。

あえて入力フォーム画面と結果画面に分けました。

```
+-入力フォーム画面---+               +-結果画面----------+
|                 |               |　　　　　　　　　　　|
| お名前: ______   | ==(Submit)==> | こんにちは{{名前}}  |
|                 |               |                  |
+-----------------+               +------------------+
```

さらに、ルーティング対象となるビュー（画面）コンポーネントと、その中身のコンポーネントに分けました。こうすることで、別のビュー（画面）にコンポーネントを引っ越したり、使いまわしたりできます。

* ビュー（画面）コンポーネント
    * Home
    * Result
* 中身のコンポーネント
    * HelloForm
    * HelloResult

# まずファイルを用意しました

* src
    * views
        * Home.vue
        * Result.vue
    * components
        * HelloForm.vue
        * HelloResult.vue

ファイルには、とりあえずテンプレートだけ入れておきました。

```vue
<template>
  <div>
  </div>
</template>
```

# 使用するコンポーネントを書きました

ビュー（画面）コンポーネントに、それぞれが使用するコンポーネントを書きました。

まず`src/views/Home.vue`です。

```vue
<template>
  <div>
    <HelloForm></HelloForm>
  </div>
</template>
<script>
import { defineComponent } from "vue";
import HelloForm from "@/components/HelloForm.vue";

export default defineComponent({
  components: {
    HelloForm,
  },
});
</script>
```

`src/views/Result.vue` です。

```vue
<template>
  <div>
    <HelloResult></HelloResult>
  </div>
</template>
<script>
import { defineComponent } from "vue";
import HelloResult from "@/components/HelloResult.vue";

export default defineComponent({
  components: {
    HelloResult,
  },
});
</script>

```


# ルーティングを設定しました

`src/router/index.ts` ファイルを編集します。

```ts
import Home from "../views/Home.vue";
import Result from "../views/Result.vue";

const routes: Array<RouteRecordRaw> = [
  { path: "/", component: Home },
  { path: "/result", component: Result },
];
```

/ へのアクセスでHomeビューコンポーネント、/result へのアクセスでResultビューコンポーネントを表示します。

# 画面遷移するコードを書きました

画面遷移は、入力フォームの操作とは独立させたいので、`src/views/Home.vue`に画面遷移するメソッドを書きました。

```ts
export default defineComponent({
  methods: {
    goResult() {
      this.$router.push("/result");
    },
  },
});
```

# イベントを書きました

入力フォームから発行するイベントをトリガにして、画面遷移させることにします。

`src/components/HelloForm.vue` にイベントとイベントを発行するメソッドを書きました。

```ts
export default defineComponent({
  emits: ["submit"],
  methods: {
    submit() {
      this.$emit("submit");
    },
  },
});
```

# イベントハンドラを書きました

入力フォームからのイベントを受け取って、画面遷移メソッドを呼び出すように、`src/views/Home.vue`のテンプレートを変更します。

```vue
<template>
  <div>
    <HelloForm @submit="goResult()"></HelloForm>
  </div>
</template>
```

# 続きます

また長くなってしまったのでいったん終わります。
次こそvuexやります。