首页
学习
活动
专区
圈层
工具
发布

通过 Laravel 创建一个 Vue 单页面应用(二)

在这个教程中,我们通过学习怎样从 Vue 组件中的 Laravel API 加载异步数据,来继续在 Laravel 中创建一个 Vue 单页应用(SPA)。我们也会看看相关的错误处理,比如当 API 返回错误,接口如何响应。

如果你没有学习 第一部分,我们通过 Vue Router 和 Laravel 后端组建的 Vue 单页应用(SPA)。如果你想继续跟着学习的话,你应该先去完整地学习一下第一部分!

保持服务端数据简单,我们的 API 将返回假数据。在第三部分,我们将让 API 通过控制器从数据库中返回测试数据。

API 路由

Vue 单页应用是无状态的,这就要求我们发起 API 请求到 Laravel 路由的时候,需要通过定义在 routes/api.php 中的路由。API 路由没有使用 session 状态,表示应用在后端是真的没有状态。

示例中,假设我们需要一个用户列表,来演示从 Vue 应用发起一个异步请求到后端:

代码语言:javascript
代码运行次数:0
复制
Route::get('/users', function () {
    return factory('App\User', 10)->make();
});

我们的临时路由采用 模型工厂 来创建一个还没有保存到数据库的 Eloquent 模型集合。使用 make() 方法, 不会将测试数据存入数据库,反而它会返回一个新的还没有存入数据库的 App\User 实例。

在 routes/api.php 定义一个路由,意味着请求都会有一个 /api 前缀,因为这个前缀定义在应用的 RouteServiceProvider 类中:

代码语言:javascript
代码运行次数:0
复制
protected function mapApiRoutes()
{
    Route::prefix('api')
         ->middleware('api')
         ->namespace($this->namespace)
         ->group(base_path('routes/api.php'));
}

结果是 GET /api/users,示例会类似下面这样:

代码语言:javascript
代码运行次数:0
复制
[
   {
      "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 路由:

代码语言:javascript
代码运行次数:0
复制
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 )像下面这样:

代码语言:javascript
代码运行次数:0
复制
<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 ),控制台数据的样子:

另一个希望你注意的是 解构 ,如下:

代码语言:javascript
代码运行次数:0
复制
<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 中, 添加一个指向用户路由的链接:

代码语言:javascript
代码运行次数:0
复制
<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文件来设置用户数据:

代码语言:javascript
代码运行次数:0
复制
fetchData() {
    this.error = this.users = null;
    this.loading = true;
    axios
        .get('/api/users')
        .then(response => {
            this.loading = false;
            this.users = response.data;
        });
}

现在,如果刷新页面,您应该会看到类似以下内容:

错误处理

组件通常要运行地符合预期,但是我们还没有针对 API 错误的处理。我们在 API 中模拟一个服务端错误:

代码语言:javascript
代码运行次数:0
复制
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():

代码语言:javascript
代码运行次数:0
复制
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 属性:

代码语言:javascript
代码运行次数:0
复制
<div v-if="error" class="error">z`
    <p>{{ error }}</p>

    <p>
        <button @click.prevent="fetchData">
            Try Again
        </button>
    </p>
</div>

现在如果失败了,UI 应该像下面这样:

总结

在这个简短的文章中,我们添加了一个新的路由从无状态的 Laravel API 中来获取一些假的用户。我们使用 “后置导航” 来针对性的获取数据。 或者采用其他的方式,比如在组件创建的时候从 API 中获取。

在 第三部分 我们尝试在 Vue Router 中使用一个回调来获取数,在导航到组件之前,让你看看如何在渲染 router view 之前获取数据。

我们也会转换 API 为从已经初始化的数据库表获取数据,因此我们可以通过设置路由参数来导航到一个具体的用户。

现在,来看看通过 Laravel 创建一个 Vue 单页面应用的 第三部分 !


原文地址:https://laravel-news.com/building-vue-spa-laravel-part-2

译文地址 :https://learnku.com/laravel/t/34281

下一篇
举报
领券