Лекции
September 17, 2020

Своя фриланс-биржа #10. Регистрация, авторизация. Vue. Bootstrap. Axios.

Вступление

Привет! Это десятый урок из моего большого онлайн-курса по созданию свой собственной фриланс-биржи с использованием django и vue. В прошлом уроке мы закончили делать макет в фигме, а значит — пора приступать к фронтенду.

Превью ролика и статьи

Думаю, логично было бы начать с авторизации и регистрации, чем мы сегодня и займёмся. Как я уже и говорил, — мы будем использовать Bootstrap для простого и быстрого создания красивого UI для нашей фриланс-биржи.

Установка и подключение Bootstrap

Начнём с его установки:

$ npm i bootstrap bootstrap-vue -S

Теперь нам надо его импортировать, это можно сделать напрямую в main.js, дописав следующий фрагмент кода:

import { BootstrapVue } from 'bootstrap-vue';

import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-vue/dist/bootstrap-vue.css';

Vue.use(BootstrapVue);

Работа с компонентами

Первое, что мы сделаем, это застилизуем наш App.vue, чтобы везде прослеживались единые детали из нашего дизайна. Это, конечно же, navbar и footer.

Обновлённый код App.vue:

<template>
 <div id="app">
   <header class="bg-dark">
     <b-navbar class="w-75 mx-auto" type="dark" variant="dark">
       <b-navbar-brand>Naive freelance</b-navbar-brand>
       <b-navbar-nav>
         <b-nav-item href="#">Главная</b-nav-item>
         <b-nav-item href="#">Заказы</b-nav-item>
         <b-nav-item href="#">Услуги</b-nav-item>
         <b-nav-item href="#">О нас</b-nav-item>
       </b-navbar-nav>
     </b-navbar>
   </header>
   <div class="container-fluid my-5">
     <router-view />
   </div>
   <footer>
     <b-jumbotron bg-variant="dark" text-variant="white">
       <div class="w-75 mx-auto">
         <div class="row">
           <div class="col-4 text-left">© Naive freelance, 2020</div>
           <div class="col-4 text-center">Контакты</div>
           <div class="col-4 text-right">О нас</div>
         </div>
       </div>
     </b-jumbotron>
   </footer>
 </div>
</template>
<script>
export default {
 name: 'App',
};

</script>
<style>
.navbar,
.navbar-brand {
 font-size: 16pt;
}

footer {
 font-size: 20pt;
}

</style>

Создадим две компоненты auth/SignIn.vue и auth/SignUp.vue, добавим в них простую разметку.

SignIn.vue:

<template>
 <div class="w-25 mx-auto border p-3 rounded">
   <b-form @submit="login">
     <div class="form-group">
       <label for="username">Логин:</label>
       <b-input v-model="username" type="text" id="username" placeholder="Логин..."></b-input>
     </div>
     <div class="form-group">
       <label for="password">Пароль:</label>
       <b-input v-model="password" type="password" id="password" placeholder="Пароль..."></b-input>
     </div>
     <b-button variant="primary" type="submit">Войти</b-button>
     <p class="mt-3">Ещё не зарегистрированы? <router-link to="/auth/signup">Регистрация</router-link>
     </p>
   </b-form>
 </div>
</template>
<script>
export default {
 name: "SignIn",
 data() {
   return {
     username: "",
     password: ""
   };
 },
 methods: {
   login(event) {
     event.preventDefault();

     // логика авторизации
    },
 }
};

</script>
<style>
</style>

SignUp.vue:

<template>
 <div class="w-50 border rounded p-3 mx-auto">
   <b-form @submit="register">
     <div class="form-group">
       <label for="username">Логин:</label>
       <b-input v-model="username" type="text" id="username" placeholder="Логин..."></b-input>
     </div>
     <div class="form-group">
       <label for="phone">Номер телефона:</label>
       <b-input v-model="phone" type="text" id="phone" placeholder="+7 (921) 123 45 67"></b-input>
     </div>
     <div class="form-group">
       <label for="customerOrExecutor">Вы заказчик или исполнитель?</label>
       <b-select v-model="customerOrExecutor" :options="customerOrExecutorOptions" type="customerOrExecutor" id="customerOrExecutor">
       </b-select>
     </div>
     <div class="form-group">
       <label for="password">Пароль:</label>
       <b-input v-model="password" type="password" id="password" placeholder="Пароль..."></b-input>
     </div>
     <div class="form-group">
       <label for="repeatPassword">Повторите пароль:</label>
       <b-input v-model="repeatPassword" type="password" id="repeatPassword" placeholder="Повторите пароль..."></b-input>
     </div>
     <b-button variant="primary" type="submit">Регистрация</b-button>
     <p class="mt-3">Уже есть аккаунт? <router-link to="/auth/signin">Вход</router-link>
     </p>
   </b-form>
 </div>
</template>
<script>
export default {
 name: "SignUp",
 data() {
   return {
     username: "",
     password: "",
     repeatPassword: "",
     phone: "",
     customerOrExecutor: "",
     customerOrExecutorOptions: [
       { text: 'Выберите...', value: '', disabled: true, selected: true },
       { text: 'Заказчик', value: 'customer' },
       { text: 'Исполнитель', value: 'executor' }
     ]
   };
 },
 methods: {
   register(event) {
     event.preventDefault();

     // логика регистрации
   }
 }
};

</script>
<style>
</style>

Пишем сами скрипты

Не забываем подключить axios к началу работы со скриптами авторизации и регистрации. Потому, что мы должны общаться с сервером.

Сделать это можно дописав в main.js всего пару строчек кода:

import axios from 'axios'
import VueAxios from 'vue-axios'

Vue.use(VueAxios, axios)

...
/* eslint-disable no-new */
new Vue({
 el: '#app',
 router,
 components: { App },
 template: '<App/>',
 ...,
 axios
});

Теперь допишем логику для авторизации:

  this.axios
    .post(`http://localhost:8000/api/auth/token/`, { 'username': this.username, 'password': this.password })
    .then(response => { this.setLogined(response.data.token) })
    .catch(err => { console.error(err) })

И логику для регистрации:

  this.axios
    .post(`http://localhost:8000/api/auth/users/`, { 'username': this.username, 'password': this.password })
    .then(response => { this.$router.push('/auth/signin') })
    .catch(err => { console.error(err) })

Роутинг

С роутингом сегодня всё очень просто, дальше будет сложнее. А пока просто подключаем компоненты и делаем на них понятные роуты:

import Vue from 'vue';
import Router from 'vue-router';
import SignIn from '@/components/auth/SignIn';
import SignUp from '@/components/auth/SignUp';

Vue.use(Router);

export default new Router({
 mode: 'history',
 routes: [
   {
     path: '/auth/signin',
     name: 'SignIn',
     component: SignIn,
   },
   {
     path: '/auth/signup',
     name: 'SignUp',
     component: SignUp,
   },
 ],
});

Параметру mode назначаем значение history, чтобы использовать History API. О нём чуть подробнее могу рассказать в одном из следующих роликов, если хотите.

Заключение

Сегодня мы научились работать с Bootstrap внутри Vue, писать базовую логику для авторизации/регистрации через фронтенд, используя axios, в следующем уроке курса мы немного дополним логику регистрации и авторизации, сделав валидацию для каждого из полей. Постараюсь сделать всё возможное, чтобы он вышел как можно быстрее. Не забывайте про мой телеграм-канал. Ещё буду признателен, если вы поставите мне звёздочки на github. Исходники можете найти там же! До скорого!