2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue.jsとDjango-Rest-Frameworkで神経衰弱アプリを作ってみる【その6】~ユーザ認証編2~

Last updated at Posted at 2020-02-16

<< その5

ログインを実装

ログイン画面作成

Login.vue
<template>
  <v-form>
    <v-container>
      <v-row>
        <v-col cols="12">
          <v-text-field
            v-model="username"
            label="Username"
            outlined
          ></v-text-field>
        </v-col>
      </v-row>

      <v-row>
        <v-col cols="12">
          <v-text-field
            v-model="password"
            outlined
            label="Password"
            style="min-height: 96px"
            type="password"
          >
          </v-text-field>
        </v-col>
      </v-row>

      <div class="text-right">
        <v-btn depressed large color="primary">ログイン</v-btn>
      </div>
    </v-container>
  </v-form>
</template>

<script>
export default {
  name: 'Login',
  data: function () {
    return {
      username: null,
      password: null
    }
  },
  mounted () {
    //
  }
}
</script>

router/index.tsを修正

router/index.ts
import Vue from 'vue'
import Router from 'vue-router'
import PlayScreen from '@/views/PlayScreen.vue'
import Login from '@/views/Login.vue'

Vue.use(Router)

export default new Router({
  mode:'history',
  routes: [
    {
      path: '/',
      redirect: 'login'
    },
    {
      path: '/login',
      name: 'login',
      component: Login
    },
    {
      path: '/playscreen',
      name: 'playscreen',
      component: PlayScreen
    },
  ]
})

npm run devすると作成したログイン画面が初期表示されるようになります。

image.png

vuexのインストール

npm install vuex --save

axiosをインストール

axiosは「Promise ベースの HTTP クライアント」です(公式より)。

npm install axios --save

axiosでget, postリクエストを投げる共通関数を用意

src直下にapiフォルダを用意し、またその直下にcommon.tsを作成してaxiosの共通関数を用意

concentratio # プロジェクトルートディレクトリ
├── config
│   ├── ...
│
├── frontend
│   ├── ...
│   ├── ..
│   ├── .
│   └── src
│         └──api # 作成
│             └──common.ts # 作成
└── manage.py
src/api/common.ts
import axios from "axios";

const baseRequest = axios.create({
  baseURL: "http://localhost:8000",
  headers: {
      "Content-Type": "application/json",
  }
});

/**
 * GETリクエスト
 * @param url URL
 */
function get(url) {
  return baseRequest.get(url);
}

/**
 * POSTリクエスト
 * @param url URL
 */
function post(url, payload) {
  return baseRequest.post(url, payload);
}

export default {
    get,
    post
};

認証用のvuexモジュールを用意

単一のgettersやactionsで管理するとソースコードが膨れ上がるだけだなあと思って機能毎にモジュール分割してみようと思って挑んだのですが、見事に半日ほどハマりました・・・。
concentratio # プロジェクトルートディレクトリ
├── config
│   ├── ...
│
├── frontend
│   ├── ...
│   ├── ..
│   ├── .
│   └── src
│         └──store # 作成
│             └──authenticates # 作成
│                 ├──actions.ts # 作成
│                 └──index.ts.ts # 作成
│                 └──mutations.ts # 作成
└── manage.py
store/authenticates/actions.ts
import commonAxios from "../../api/common";

export default {
  LOGIN: function({ commit }, payload) {
    return new Promise((success, error) => {
      commonAxios.post("/api-token-auth/", payload).then(
        response => {
          // 成功時の処理
          commit("SET_TOKEN", response.data.token); // mutations.tsのSET_TOKEN関数にトークンを渡す
          commonAxios.baseRequest.defaults.headers.common['Authorization'] = `JWT ${response.data.token}`;
          success();
        }
      );
    });
  }
}

上記、urlの最後に"/(スラッシュ)"を付け忘れるとCORSではじかれてエラーになります。 これにも気づくのに時間がかかって小一時間ほどハマりました・・・。    
store/authenticates/index.ts
import actions from './actions';

export const state = {};

export default {
  namespaced: true, // 必ずつける、外すとvueのmapActionsで読み込む時にエラーになるよ。
  state,
  actions,
  mutations
};

store/authenticates/mutations.ts
export default {
  SET_TOKEN: function(state, token) {
    state.token = token
  }
};

src/store直下にindex.tsを作成

store/index.ts
import Vue from "vue";
import Vuex from "vuex";
import authModules from "./authenticates"; // authenticates配下のモジュールをauthModulesという名前で読み込む

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    authModules: authModules,
  }
});

src/main.tsを修正

src/main.ts
.
..
...
import store from "./store"; // 追加
...
..
.
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>',
  vuetify: new Vuetify(),
  store // 追加
});

Login.vueを修正

Login.vue
<template>
  <v-form>
    <v-container>
      ...
      ..
      .

      <div class="text-right">
        <v-btn depressed large color="primary" @click="login">
          ログイン
        </v-btn>
      </div>
    </v-container>
  </v-form>
</template>

<script>
import { mapActions } from "vuex";

export default {
  name: "Login",
  data: function() {
    return {
      username: null,
      password: null
    };
  },
  methods: {
    ...mapActions("authModules", ["LOGIN"]), // モジュール分割したaction.tsからLOGIN関数を読み込み
    login: function() {
      const data = {
        username: this.username,
        password: this.password
      };
      this.LOGIN(data).then(res => {
        console.log(res);
      });
    }
  },
  mounted() {
    //
  }
};
</script>

responseが返ってくるか確認

正しいusernameとpasswordを入力後ログインボタン押下でresponseが返ってくる確認します。

image.png

返ってきました!

認証成功後、トップページに遷移するようにする。

Login.vueconsole.log(res);this.$router.push("/playscreen");に書き換えるだけ。

以上

無事、ログイン画面からトップページに遷移することができました。

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?