使用 Laravel 构建 Vue SPA - 第 2 部分

发布日期:作者:

Building a Vue SPA with Laravel Part 2 image

在本教程中,我们将继续学习如何使用 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",
},
{
"name":"Prof. Clarissa Osinski",
},
{
"name":"Myrtle Wyman",
},
...
]

客户端路由

如果您在第 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 部分

Paul Redmond photo

Laravel 新闻的编外作者。全栈 Web 开发人员和作者。

Cube

Laravel 新闻简报

加入 40,000 多名其他开发人员,不错过任何新的技巧、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动补全和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

No Compromises

Joel 和 Aaron,来自 No Compromises 播客的两位经验丰富的开发者,现在可以为您的 Laravel 项目聘请。 ⬧ 固定价格 7500 美元/月。 ⬧ 无需漫长的销售流程。 ⬧ 无需合同。 ⬧ 100% 退款保证。

No Compromises
Kirschbaum logo

Kirschbaum

提供创新和稳定性,以确保您的 Web 应用程序成功。

Kirschbaum
Shift logo

Shift

正在运行旧的 Laravel 版本?即时自动的 Laravel 升级和代码现代化,让您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

只需 2500 美元/月,即可为您的项目配备一位经验丰富的 Laravel 开发人员(4-6 年经验)。获得 160 小时的专业知识和 15 天的无风险试用。立即安排通话!

Bacancy
Lucky Media logo

Lucky Media

现在就来试试 Lucky - Laravel 开发的理想选择,拥有十多年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel 电子商务

Laravel 的电子商务。一个开源软件包,将现代无头电子商务功能的强大功能带入 Laravel。

Lunar: Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 职位板

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS 启动套件

SaaSykit 是一个 Laravel SaaS 启动套件,包含运行现代 SaaS 所需的所有功能。支付、漂亮的结账、管理面板、用户仪表板、身份验证、就绪组件、统计信息、博客、文档等等。

SaaSykit: Laravel SaaS 启动套件
Rector logo

Rector

您无缝升级 Laravel、降低成本并加速创新的合作伙伴,为成功公司提供服务

Rector
MongoDB logo

MongoDB

通过 MongoDB 和 Laravel 的强大集成来增强您的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。支持事务、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。了解 MongoDB 的灵活、现代数据库如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

在您的 Laravel 应用程序中添加 Swagger UI

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel 提示构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 软件包在您的 Laravel 应用程序中添加评论

阅读文章