Skip to content

Vueで複数画面構成を作る router設定#

通常、Webアプリケーションはいろいろな機能を持っており、機能によっては画面を複数にして構成します。 たとえば、アンケートアプリだと、 * アンケートを回答する画面 * アンケートを確認する画面 などです。

ここでは、アンケートを回答する画面とアンケートを確認する画面をVueのRouterという機能を使って構成します。

前提#

アンケートアプリをここまで作成してください。

Routerの設定#

Routerは、URLのパスに画面を割り当てることができます。 URLは

{プロトコル}://{ドメイン名(サーバ名)}/{パス}

のような形式で出来上がっています。 早速、パスにより画面が切り替わるようにしていきます。

まずは Vue Routerをインストールします。 ターミナルのnpmディレクトリにて、以下のコマンドを実行します。

npm install vue-router

パスに割り当てるコンポーネントを作成します。今回はアンケートの結果を一覧で表示するコンポーネントを作成します。

src/front/components/EnqueteResultList.vue を以下の内容で作成してください。

<template>
  <div>
    <h1>アンケート回答一覧</h1>
    <table>
      <tr>
        <th>点数</th>
        <th>ご意見ご要望</th>
        <th>メールアドレス</th>
      </tr>
      <tr v-for="enquete in enquetes" :key="enquete.id">
        <td>{{enquete.point}}</td>
        <td>{{enquete.message}}</td>
        <td>{{enquete.mail}}</td>
      </tr>
    </table>
  </div>
</template>
<script lang="ts">
import Vue from "vue";
import axios from "axios";

export default Vue.extend({
  data() {
    return {
      enquetes: [],
    };
  },
  async created() {
    const response = await axios.get("/api/enquetes");
    this.enquetes = response.data;
  },
});
</script>

サーバ側のAPIを作成します。 src/backend/controllers/enquete.ts を編集、5行追加します。

import express, { Router } from 'express'
import { getRepository } from 'typeorm'
import Enquete from '../models/Enquete'

var router: Router = express.Router();

router.post('/', async function (req, res) {
    const enquete = req.body;
    const EnqueteRepository = getRepository(Enquete);
    await EnqueteRepository.save(enquete);
    res.send(enquete);
});
//ここから
router.get('/', async function (req, res) {
    const EnqueteRepository = getRepository(Enquete);
    const enquetes = await EnqueteRepository.find();
    res.send(enquetes);
});
//ここまで追加
export default router;

これで、EnqueteResultListコンポーネントが動くようになりました。

このコンポーネントを パス /enquete/list に割り当てます。

次に、src/front/components/App.vue にrouteの設定をします。

<template>
  <div>
    <router-view /><!-- post-enquete  router-view に変更します -->
  </div>
</template>
<script lang="ts">
import Vue from "vue";
import VueRouter from "vue-router";//この行を追加
import PostEnquete from "./PostEnquete.vue";
import EnqueteResultList from "./EnqueteResultList.vue";//この行を追加

//ここから
const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '/', component: PostEnquete },
    { path: '/enquete/list', component: EnqueteResultList }
  ]
})
//ここまで追加
Vue.use(VueRouter);//この行を追加
export default Vue.extend({
  router //この行を追加
  //components: { PostEnquete }, // この行を消します
});
</script>

パスにコンポーネントを割り当てるためには、 templateタグの中で差し替えたい場所をrouter-viewタグにして、 パスとコンポーネントの関連をVueRouterに設定します。

最後に、サーバでは、API以外のどのパスにリクエストされても、index.htmlを返却するようにします。 src/backend/index.tsに3行追加します。

import express from 'express'
import messageController from './controllers/message'
import enqueteController from './controllers/enquete'
import { createConnection } from 'typeorm'

import Enquete from './models/Enquete'

const app: express.Express = express()

app.use(express.json())
app.use(express.urlencoded({ extended: true }))

app.use("/messages", messageController)
app.use("/api/enquetes", enqueteController)
app.use("/", express.static(__dirname + "/public"))
//ここから
app.get('*', (req, res) => {
    res.status(200).sendFile(__dirname + "/public/index.html");
});
//ここまで追加

!async function initialize() {
    await createConnection({
        type: "postgres",
        url: process.env.DATABASE_URL || "postgres://postgres:postgres@localhost:5432/postgres",
        synchronize: true,
        entities: [
            Enquete,
        ],
        extra: {
            ssl: (!!process.env.DATABASE_SSL) ? {
                rejectUnauthorized: false,
            } : false,
        }
    });
    const port = process.env.PORT || 3000;
    app.listen(port, () => {
        console.log("ポート" + port + "番で起動しました!")
    })
}()

更に、index.htmlがどのパスでアクセスされてもbundle.jsが読めるように修正を加えます。 src/front/public/index.html を一行(一文字)修正します。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>My App</title>
    </head>
    <body>
        <div id="app"></div>
        <script src="/js/bundle.js"></script><!-- パスの前の . を削除。絶対パスで読めるようにする。-->
    </body>
</html>

これにより、ブラウザでhttp://localhost:3000/enquete/list を入力しても、index.htmlが表示されるようになりました。 index.htmlによって読み込まれたVueが、パスを見て、ブラウザ上でアンケート一覧を表示します。

これで、複数画面構成を作成することができるようになりました。 ただ、これではアンケート結果がみんなから丸見えですね。次はアンケート結果のページはログインしていないと見れないようにします。