共计 4130 个字符,预计需要花费 11 分钟才能阅读完成。
在这个教程中,我们通过学习怎样从 Vue
组件中的 Laravel API
加载异步数据,来继续在 Laravel
中创建一个 Vue
单页应用(SPA)。我们也会看看相关的错误处理,比如当 API
返回错误,接口如何响应。
如果你没有学习第一部分,我们通过 Vue Router
和 Laravel
后端组建的 Vue
单页应用(SPA)。如果你想继续跟着学习的话,你应该先去完整地学习一下第一部分!
保持服务端数据简单,我们的 API
将返回假数据。在第三部分,我们将让 API
通过控制器从数据库中返回测试数据。
API 路由
Vue
单页应用是无状态的,这就要求我们发起 API
请求到 Laravel
路由的时候,需要通过定义在 routes/api.php
中的路由。API
路由没有使用 session
状态,表示应用在后端是真的没有状态。
示例中,假设我们需要一个用户列表,来演示从 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":"catharine.kreiger@example.net"
},
{
"name":"Prof. Clarissa Osinski",
"email":"wilfrid.kiehn@example.com"
},
{
"name":"Myrtle Wyman",
"email":"dan31@example.com"
},
...
]
客户端路由
在 第一部分
中,我们在 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
的生命周期钩子(新建,加载,等等)。
在这个组件中,在组件 创建 的时候获取异步数据。定义一个 fechData()
方法来初始化 error
和 users
属性为 null
,设置 loading
为 true。
fetchData()
方法中最后一行使用 Axios 库来向 Laravel API
发起一个 HTTP
请求。Axios
是一个 promise-based HTTP
客户端,通过链式调用 then()
回调来记录返回并且最终赋值给 users
数据属性。
下面是在应用中加载 /users
(客户端页面,而非 API
),控制台数据的样子:
另一个希望你注意的是 解构,如下:
<li v-for="{name, email} in users">
<strong>Name:</strong> {{name}},
<strong>Email:</strong> {{email}}
</li>
解构是一种有效的方式来为某个对象来提取 props
,而且简洁 / 易懂。
完成路由组件
我们现在有一个 /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 prpmise
上链式调用 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
中获取。
在 第三部分 我们尝试在 Vue Router
中使用一个回调来获取数,在导航到组件 之前,让你看看如何在渲染 router view
之前获取数据。
我们也会转换 API
为从已经初始化的数据库表获取数据,因此我们可以通过设置路由参数来导航到一个具体的用户。
现在,来看看通过 Laravel
创建一个 Vue
单页面应用的 第三部分!