使用 Laravel 构建 Vue SPA - 第 2 部分
发布日期:作者: Paul Redmond
在本教程中,我们将继续学习如何使用 Laravel 构建 Vue 单页应用程序 (SPA),包括如何在 Vue 组件中从 Laravel API 端点加载异步数据。我们还将探讨 API 响应返回错误时的错误处理方法,以及如何在界面中做出响应。
如果您没有阅读 第 1 部分,我们已经介绍了如何使用 Vue Router 和 Laravel 后端来连接 Vue 单页应用程序 (SPA)。如果您想跟随教程,应该先阅读第 1 部分!
为了简化服务器端数据,我们的 API 将使用假数据。在第 3 部分,我们将把 API 转换为使用数据库测试数据的控制器。
API 路由
Vue SPA 应用程序是无状态的,这意味着我们对 Laravel 路由器进行 API 调用,并在 routes/api.php
文件中定义我们的路由。API 路由不使用会话状态,这意味着我们的应用程序在后端确实是无状态的。
在我们的示例中,假设我们想要获取一个用户列表,以便演示从我们的 Vue 应用程序异步请求后端。
Route::get('/users', function () { return factory('App\User', 10)->make();});
我们的临时路由使用 模型工厂 来创建一个 Eloquent 模型集合,这些模型尚未持久化到数据库中。我们使用 make()
方法,该方法不会尝试将测试数据插入数据库,而是返回一个尚未持久化的新的 App\User
实例的集合。
在 routes/api.php
文件中定义路由意味着我们的请求具有 /api
的前缀,因为这是应用程序的 RouteServiceProvider
类中定义的前缀。
protected function mapApiRoutes(){ Route::prefix('api') ->middleware('api') ->namespace($this->namespace) ->group(base_path('routes/api.php'));}
我们的用户资源是 GET /api/users
,一个示例响应可能如下所示:
[ { "name":"Roel Rosenbaum I", "email":"[email protected]" }, { "name":"Prof. Clarissa Osinski", "email":"[email protected]" }, { "name":"Myrtle Wyman", "email":"[email protected]" }, ...]
客户端路由
如果您在第 1 部分中跟随教程,我们在 resources/assets/js/app.js
文件中构建了几个路由,以演示 SPA 之间的导航。每次我们想添加一个新的路由时,我们在 routes
数组中创建一个新的对象,该对象定义每个路由的路径、名称和组件。最后一个路由是我们的新的 /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 的 组件 文档,并熟悉 Vue 生命周期钩子(created、mounted 等)。
在这个组件中,我们正在组件创建钩子期间获取异步数据。我们定义了一个 fechData()
方法,该方法将错误和用户属性重置为 null
,并将 loading
设置为 true。
fetchData()
方法中的最后一行使用 Axios 库对我们的 Laravel API 发出 HTTP 请求。Axios 是一个基于 Promise 的 HTTP 客户端,我们使用它来链接 then()
回调,在该回调中,我们记录响应,并将最终将其设置为 users
数据属性。
以下是您在应用程序中加载 /users
时控制台数据的样子(客户端页面,而不是 API):
我还想让您注意这里发生的 对象解构
<li v-for="{ name, email } in users"> <strong>Name:</strong> {{ name }}, <strong>Email:</strong> {{ email }}</li>
对象解构是一种高效的方式,可以只获取对象所需的属性,并且更加简洁易读。
完成路由组件
我们有了 /users
的路由和组件,让我们在主 App
组件中添加一个导航链接,然后设置来自 users
响应的用户数据。
在 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>
接下来,让我们更新 UsersIndex.vue
文件以设置用户数据。
fetchData() { this.error = this.users = null; this.loading = true; axios .get('/api/users') .then(response => { this.loading = false; this.users = response.data; });}
现在如果您刷新页面,您应该会看到类似以下内容:
处理错误
我们的组件应该在大多数情况下按预期工作,但我们还没有处理 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()
在数字小于 3 时中止请求。如果您刷新页面几次,您应该会看到“正在加载...”,如果您检查开发人员工具,您将看到来自 Axios 请求的未捕获异常。
我们可以通过在 Axios Promise 上链接 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
,并使用错误异常来尝试从响应中设置 message
键。该消息回退到 exception.message
属性。
为了确保万无一失,让我们在这个条件下在 UsersIndex.vue
模板中为用户提供一个“重试”按钮,该按钮简单地调用我们的 fetchData
方法来刷新 users
属性。
<div v-if="error" class="error"> <p>{{ error }}</p> <p> <button @click.prevent="fetchData"> Try Again </button> </p></div>
现在如果发生错误,UI 应该看起来像这样:
结论
在这篇简短的文章中,我们向无状态 Laravel API 端点添加了一个新的路由,以列出一些假用户。我们使用“导航后”数据获取策略来获取数据。或者换句话说,我们是在组件创建时从 API 请求数据的。
在 第 3 部分 中,我们将探讨在 Vue Router 中使用回调在导航到组件之前获取数据,以向您展示如何在呈现路由视图之前获取数据。
我们还将把 API 转换为使用带有种子数据的数据库表,以便我们可以讨论导航到单个用户,这包括使用路由参数。
现在,让我们继续学习使用 Laravel 构建 Vue SPA 的 第 3 部分!