Laravel mix vue2 - Vue router, Vue component

こんにちは、あすかのkoheiです。

前回環境を構築したので、今回はvue router と componentを使ってみます。

前回の記事はLaravel mix vue1 - enveronment - Dockerでlaravel環境

Vue Router

フォルダ構成


└─ server
   └─ resources
      └─ js
+        ├─ components
+        │  └─ Header.vue
+        ├─ pages
+        │  ├─ errors
+        │  │  ├─ NotFound.veu
+        │  │  └─ SystemError.vue
+        │  ├─ Home.vue
+        │  └─ Login.vue
         ├─ app.js
+        ├─ App.vue
+        └─ router.js

開発用にchrome拡張機能を追加

chromeブラウザで、「chrome ウェブストア」から Vue.js devtoolsを追加


dockerスタート

# コンテナスタート
docker-compose start

# コンテナに入る
docker-compose exec php bash

# ホットリリード開始
npm run watch

vueファイルの作成

コンポーネントの作成

<template>
  <header>
    <!-- リンクを設定 -->
    <RouterLink to="/">home</RouterLink>
    <RouterLink to="/login">login</RouterLink>
    <!-- クリックイベントにlogoutメソッドを登録 -->
    <span @click="logout">logout</span>

  </header>
</template>

<script>
export default {
  methods: {
    // ログアウトメソッド
    async logout() {
      // ログアウトのAPIリクエスト(次のステップで実装)
      alert("logout");
      // ログインに移動
      this.$router.push("/login");
    }

  }
};
</script>

ルートコンポーネントの作成

このファイルは server\\resources\\views\\index.blade.php<div id="app"></div>にこのコンポーネントが描画される この中のルートビューコンポーネント <RouterView />が各ページに切り替わる <Header />にはヘッダーコンポーネントが表示される

<template>
  <div>

    <!-- Headerコンポーネント -->
    <Header />

    <main>
      <div class="container">
        <!-- ルートビューコンポーネント -->
        <RouterView />
      </div>
    </main>

  </div>
</template>

<script>
// Headerコンポーネントをインポート
import Header from "./components/Header.vue";

export default {
  // 使用するコンポーネントを宣言
  components: {
    Header
  }
};
</script>

ページの作成

  • home
<template>
  <div class="container">

    <h1>Home</h1>

  </div>
</template>
  • login
<template>
  <div class="container">

    <!-- login -->
    <section class="login">
      <h2>Login</h2>
      <form class="form">
        <div>Email</div>
        <div>
          <input type="email" />
        </div>
        <div>Password</div>
        <div>
          <input type="password" />
        </div>
        <div>
          <button type="submit">login</button>
        </div>
      </form>
    </section>
    <!-- /login -->

  </div>
</template>
  • 404 not found

<template>
  <p>お探しのページは見つかりませんでした。</p>
</template>
  • 500 system error
<template>
  <p>システムエラーが発生しました。</p>
</template>

ルーターの作成

import Vue from 'vue'
// ルーターをインポート
import VueRouter from 'vue-router'

// ページをインポート
import Home from './pages/Home.vue'
import Login from './pages/Login.vue'
import SystemError from './pages/SystemError.vue'
import NotFound from './pages/NotFound.vue'

// VueRouterをVueで使う
Vue.use(VueRouter)

// パスとページの設定
const routes = [

    // home
    {
        // urlのパス
        path: '/',
        // インポートしたページ
        component: Home
    },
    // login
    {
        // urlのパス
        path: '/login',
        // インポートしたページ
        component: Login
    },
    // システムエラー
    {
        path: "/500",
        component: SystemError
    },
    // not found
    {
        // 定義されたルート以外のパスでのアクセスは <NotFound> が表示
        path: "*",
        component: NotFound
    }
]

// VueRouterインスタンス
const router = new VueRouter({
    // いつもどうりのURLを使うために「history」モードにする
    mode: 'history',
    // 設定したルートオブジェクト
    routes
})

// VueRouterインスタンスをエクスポート
export default router

app.jsの修正

    import "./bootstrap";
    import Vue from "vue";
+   // ルートコンポーネントをインポート
+   import App from "./App.vue";
+   // ルーターをインポート
+   import router from "./router";

    new Vue({
+       // マウントする要素に「index.blade.php」の「<div id="app"></div>」のidを登録
        el: "#app",
+       // ルーターの使用を宣言
+       router,
+       // 使用するコンポーネントにルートコンポーネントの登録
+       components: { App },
+       // 描画するテンプレート
+       template: "<App />"
+   });

ブラウザで確認

Home http://localhost:3000

Login http://localhost:3000/login


UIの作成

タブの作成

タブで切り替えれるログイン、 登録、 パスワード再設定のフォームを作ります。

 <template>
   <div class="container">

+    <!-- tabs -->
+    <ul class="tab">
+      <li class="tab__item"
+        :class="{'tab__item--active': tab === 1 }"
+        @click="tab = 1"
+      >Login</li>
+      <li class="tab__item"
+         :class="{'tab__item--active': tab === 2 }"
+          @click="tab = 2"
+        >Register</li>
+      <li
+        class="tab__item"
+        :class="{'tab__item--active': tab === 3 }"
+        @click="tab = 3"
+      >Forgot password ?</li>
+    </ul>
+    <!-- /tabs -->

+    <!-- login -->
-    <section class="login" >
+    <section
+      class="login"
+      v-show="tab === 1"
+    >
       <form>
         <h2>Login</h2>
         <div>Email</div>
         <div>
           <input type="email" />
         </div>
         <div>Password</div>
         <div>
           <input type="password" />
         </div>
         <div>
           <button type="submit">login</button>
         </div>
       </form>
     </section>
     <!-- /login -->

+    <!-- register -->
+    <section class="register" v-show="tab === 2">
+      <form>
+        <h2>register</h2>
+        <div>Name</div>
+        <div>
+          <input type="text" />
+        </div>
+        <div>Email</div>
+        <div>
+          <input type="email" />
+        </div>
+        <div>Password</div>
+        <div>
+          <input type="password" />
+        </div>
+        <div>Password confirmation</div>
+        <div>
+          <input type="password" />
+        </div>
+        <div>
+          <button type="submit">register</button>
+        </div>
+      </form>
+    </section>
+    <!-- /register -->

+    <!-- forgot -->
+    <section class="forgot" v-show="tab === 3">
+      <form>
+        <h2>forgot</h2>
+        <div>Email</div>
+        <div>
+          <input type="email" />
+        </div>
+        <div>
+          <button type="submit">send</button>
+        </div>
+      </form>
+    </section>
+    <!-- /forgot -->

   </div>
 </template>

+<script>
+export default {
+  // vueで使うデータ
+  data() {
+    return {
+      tab: 1,
+    };
+  }
+};
+</script>
+<style>
+.tab {
+  padding: 0;
+  display: flex;
+  list-style: none;
+}
+.tab__item {
+  border: 1px solid gray;
+  padding: 0 0.5rem;
+  margin-left: 0.1rem;
+  cursor: pointer;
+}
+.tab__item--active {
+  background-color: lightgray;
+}
+</style>

inputのバインディング

...
    <!-- login -->
    <section
      class="login"
      v-show="tab === 1"
    >
    <h2>Login</h2>
-   <form>
+   <!-- @submitで login method を呼び出し -->
+   <!-- @submitイベントリスナに prevent をつけるとsubmitイベントによってページがリロードさない -->
+   <form @submit.prevent="login">
      <div>Email</div>
      <div>
-       <input type="email" />
+       <!-- v-modelでdataをバインド -->
+       <input type="email" v-model="loginForm.email" />
      </div>
      <div>Password</div>
      <div>
-       <input type="password" />
+       <input type="password" v-model="loginForm.password" />
      </div>
      <div>
        <button type="submit">login</button>
      </div>
    </form>
    </section>
    <!-- /login -->

    <!-- register -->
    <section
      class="register"
      v-show="tab === 2"
    >
      <h2>register</h2>
-     <form>
+     <form @submit.prevent="register">
        <div>Name</div>
        <div>
-         <input type="text" >
+         <input type="text" v-model="register.name" />
        </div>
        <div>Email</div>
        <div>
-         <input type="email" >
+         <input type="email" v-model="register.email" />
        </div>
        <div>Password</div>
        <div>
-         <input type="password" />
+         <input type="password" v-model="register.password" />
        </div>
        <div>Password confirmation</div>
        <div>
-         <input type="password" />
+         <input type="password" v-model="register.password_confirmation" />
        </div>
        <div>
          <button type="submit">register</button>
        </div>
      </form>
    </section>
    <!-- /register -->

   <!-- forgot -->
    <section
        class="forgot"
        v-show="tab === 3"
    >
      <h2>forgot</h2>
-     <form>
+     <form @submit.prevent="forgot">
        <div>Email</div>
        <div>
-         <input type="email" />
+         <input type="email" v-model="forgot.email" />
        </div>
        <div>
          <button type="submit">send</button>
        </div>
      </form>
    </section>
    <!-- /forgot -->

  </div>
</template>

<script>
export default {
    // vueで使うデータ
    data() {
        return {
            tab: 1,
+           loginForm: {
+               email: "",
+               password: "",
+               remember: true
+           },
+           registerForm: {
+               name: "",
+               email: "",
+               password: "",
+               password_confirmation: ""
+           },
+           forgotForm: {
+               email: ""
+           },
        };
    },

+   methods: {
+       /*
+        * login
+        */
+       async login() {
+           alert("login");
+           this.clearForm();
+       },

+       /*
+        * register
+        */
+       async register() {
+           alert("register");
+           this.clearForm();
+       },

+       /*
+        * forgot
+        */
+       async forgot() {
+           alert("forgot");
+           this.clearForm();
+       },

+       /*
+        * clear form
+        */
+       clearForm() {
+           // login form
+           this.loginForm.email = "";
+           this.loginForm.password = "";
+           // register form
+           this.registerForm.name = "";
+           this.registerForm.email = "";
+           this.registerForm.password = "";
+           this.registerForm.password_confirmation = "";
+           // forgot form
+           this.forgot.email = "";
+       },
+   }
};
...

これで、UI完成、Vueだけでルーティングできるようになった!

次はこれLaravel mix vue3 - Authentication API

okuda

Webdeveloper

Laravel mix vue2 - Vue router, Vue component

お気軽に
お問い合わせください。

お問い合わせ