В этой части мы продолжим создавать Single Page Application (SPA) с помощью Vue и Laravel. В этой части мы научимся:
- Асинхронно загружать данные из Vue компонентов
- Обрабатывать ошибки которые возвращает наш API
- Показывать загруженные данные нашему пользователю
- ... и многое другое
Если вы еще не читали первую часть, то советую вам начать с нее. В ней мы настроили наше приложение, создали несколько компонентов и научились собирать собирать Javascript с помощью yarn.
Наше API будет возвращать фейковые данные, дабы не усложнять наш backend. В 3й части мы изменим это, и будем возвращать данные из базы данных.
API маршруты
SPA приложение не имеют состояния (stateless
), что означает, что каждый API запрос считается новым, и не хранит состояние в сессии, как это бывает с обычными (не SPA) приложениями.
Давайте для примера зададим users
маршрут, который будет возвращать список пользователей. Откройте файл routes/api.php
и добавьте в него код:
Route::get('/users', function () {
return factory('App\User', 10)->make();
});
Наш временный маршрут использует фабрику моделей для создания Eloquent Collection
с моделями (без того чтобы создавать их в базе данных).
Вы должны помнить, что ко всем маршрутам заданным в файле routes/api.php
автоматически добавляется префикс api
. Изменить это вы можете в файле RouterServiceProvider в методе mapApiRoutes():
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
Пример ответа для маршрута users
выглядит так:
[
{
"name":"Roel Rosenbaum I",
"email":"[email protected]"
},
{
"name":"Prof. Clarissa Osinski",
"email":"[email protected]"
},
{
"name":"Myrtle Wyman",
"email":"[email protected]"
},
...
]
Клиентские маршруты
В первой части мы добавили несколько клиентских маршрутов в файле resouces/assets/js/app.js. Напомним, чтобы добавить новый маршрут в VueRouter, необходимо создать новый объект в котором указать: имя, путь и компонент. Добавим новый маршрут users:
import UsersIndex from './views/UsersIndex';
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/hello',
name: 'hello',
component: Hello,
},
{
path: '/users',
name: 'users.index',
component: UsersIndex,
},
],
});
Компонент UsersIndex
Выше, в качестве компонента мы указали UsersIndex. Теперь нам необходимо его создать. Создайте файл resources/assets/js/views/UsersIndex.vue и добавьте в него следующий код:
<template>
<div class="users">
<div class="loading" v-if="loading">
Loading...
</div>
<div v-if="error" class="error">
{{ error }}
</div>
<ul v-if="users">
<li v-for="{ name, email } in users">
<strong>Name:</strong> {{ name }},
<strong>Email:</strong> {{ email }}
</li>
</ul>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
loading: false,
users: null,
error: null,
};
},
created() {
this.fetchData();
},
methods: {
fetchData() {
this.error = this.users = null;
this.loading = true;
axios
.get('/api/users')
.then(response => {
console.log(response);
});
}
}
}
</script>
Если вы новичек в Vue или вам что-то не понятно в коде выше - не пугайтесь. Прочитайте документацию по компонентам Vue и вам все станет понятно.
В этом компоненте мы асинхронно загружаем данные во время инициализации компонента. Мы определили метод fetchData()
, который устанавливает в null
users
и error
переменные и устанавливает флаг (переменную) loading
в true
. Последняя строчка в fetchData()
загружает данные с помощью Axios библиотеки, посылая запрос на наш Laravel API.
Если вы теперь откроете браузер и перейдете по адресу /users
вы должны будете увидеть в консоли примерно следующее:
Еще одна вещь на которую вам следует обратить внимание: использование "Разбора объекта":
<li v-for="{ name, email } in users">
<strong>Name:</strong> {{ name }},
<strong>Email:</strong> {{ email }}
</li>
С помощью "Разбора объекта" вы можете взять только нужные вам элементы из объекта, и откинуть все остальное.
Заканчиваем с Route компонентом
У нас уже есть маршрут и компонет которые обрабатывают /users URI. Давайте добавим ссылку для навигации в наш главный шаблон.
Откройте файл resources/assets/js/views/App.vue
и добавьте ссылку:
<template>
<div>
<h1>Vue Router Demo App</h1>
<p>
<router-link :to="{ name: 'home' }">Home</router-link> |
<router-link :to="{ name: 'hello' }">Hello World</router-link> |
<router-link :to="{ name: 'users.index' }">Users</router-link>
</p>
<div class="container">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {}
</script>
Если вы теперь обновите страницу, вы должны увидеть следующее:
Обработка ошибок
До этого момента наш компонент работал нормально, но что если API вернет нам ошибку? Давайте добавим симуляцию ошибки в наш API:
Route::get('/users', function () {
if (rand(1, 10) < 3) {
abort(500, 'We could not retrieve the users');
}
return factory('App\User', 10)->make();
});
Тут мы используем функцию rand()
чтобы симулироваь случайную ошибку. Если вы сейчас несколько раз обновите страницу, вы должны будете увидеть ошибку в консоли:
Мы можем обработать эту ошибку с помощью метода catch()
:
fetchData() {
this.error = this.users = null;
this.loading = true;
axios
.get('/api/users')
.then(response => {
this.loading = false;
this.users = response.data;
}).catch(error => {
this.loading = false;
this.error = error.response.data.message || error.message;
});
}
Тут мы устанавливаем переменную loading
в false
и записываем ошибку в переменную error
.
Давайте добавим кнопку "Try Again", для улучшения юзабилити, при нажатии на которую будет вызываться метод fetchData()
:
<div v-if="error" class="error">
<p>{{ error }}</p>
<p>
<button @click.prevent="fetchData">
Try Again
</button>
</p>
</div>
Теперь, если вы будете обновлять страницу, вы должны будете увидеть нечто похожее при возникновении ошибки:
Заключение
В этой короткой статье мы:
- Добавили новый маршрут в Laravel, который возвращает фейковые данные
- Добавили ссылку для навигации в App.vue
- Научились делать асинхронные запросы после перехода по ссылке с помощью Axios
- А так же научились обрабатывать HTTP ошибки с помощью Axios
В 3й части мы научимся загружать данные ДО того как будет совершен переход по ссылке.
Перевод статьи Building a Vue SPA with Laravel Part 2
Опубликовано: