在 Laravel 项目中基于 Vue + Bootstrap 快速开发表单组件


我们回到正题,在 Laravel 项目中基于纯 Vue.js 框架编写表单组件,不再依赖 Inertia 和 Livewire 技术栈。

Laravel 8.x 仍然支持并维护 laravel/ui 扩展包,所以这里我们新安装一个 Laravel 8 项目,然后基于它来演示如何通过 Vue.js 开发表单组件。

项目初始化

我们通过最新版的 Laravel 安装器新安装一个基于 Laravel 8 的 component-practice 项目:

laravel new component-practice

其他安装 laravel/ui 扩展包,初始化 Vue、Bootstrap 和前端依赖的步骤和之前一样:

cd component-practice
 
composer require laravel/ui

php artisan ui bootstrap
php artisan ui vue

npm install && npm run dev

这里不再详细介绍了,完成以上初始化步骤后,我们直接进入 Vue 表单组件开发流程。

编写 Vue 表单组件

component-practice/resources/js/components 目录下新建一个 FormComponent.vue 文件,编写文章发布表单组件代码如下:

<style scoped>
.post-form {
    margin: 50px auto;
    padding: 30px;
}
.alert {
    margin-top: 10px;
}
</style>

<template>
    <div class="card col-8 post-form">
        <h3 class="text-center">发布新文章</h3>
        <hr>
        <form @submit.prevent="store">
            <div class="form-group">
                <label for="title">标题</label>
                <input type="text" ref="title" class="form-control" id="title" v-model="article.title">
                <div class="alert alert-danger" role="alert" v-show="errors.title">
                    {{ errors.title }}
                </div>
            </div>
            <div class="form-group">
                <label for="author">作者</label>
                <input type="text" ref="author" class="form-control" id="author" v-model="article.author">
                <div class="alert alert-danger" role="alert" v-show="errors.author">
                    {{ errors.author }}
                </div>
            </div>
            <div class="form-group">
                <label for="content">内容</label>
                <textarea class="form-control" ref="content" id="content" rows="5" v-model="article.content"></textarea>
                <div class="alert alert-danger" role="alert" v-show="errors.content">
                    {{ errors.content }}
                </div>
            </div>
            <button type="submit" class="btn btn-primary">立即发布</button>
            <div class="alert alert-success" role="alert" v-show="published">
                文章发布成功。
            </div>
        </form>
    </div>
</template>

<script>

export default {

    data() {
        return {
            article: {
                title: "",
                author: "",
                content: "",
            },
            errors: {
                title: "",
                author: "",
                content: "",
            },
            published: false
        }
    },
    methods: {
        store() {
            // 先清理错误消息
            Object.entries(this.errors).forEach(error => {
                let [key, msg] = error
                this.errors[key] = "";
            });
            axios.post("/post", this.article).then(response => {
                // 请求处理成功
                this.published = true;
                console.log(response.data);
            }).catch(error => {
                // 请求验证失败
                // 获取验证错误包
                let errorBag = error.response.data;
                // 错误包中每个字段的错误信息可能有多个
                Object.entries(errorBag.errors).forEach(bag => {
                    let [field, errors] = bag;
                    if (errors.length > 0) {
                        this.errors[field] = errors.join('<br>');
                    }
                });
            });
        }
    }
}
</script>

基本功能和前面基于 InertiaLivewire 编写的表单组件一样,这是做了简化,为了方便快速构建,这里使用了 Bootstrap CSS 框架,以便可以使用其开箱提供的 CSS class。

在这个基于纯 Vue 代码编写的表单组件中,基于表单数据绑定将 HTML 模板中的文章字段数据和 Vue 模型数据进行了双向绑定,如果表单字段验证错误,还会基于条件渲染 显示验证错误信息,如果表单提交成功,也会基于条件渲染显示成功提示文案。

提交表单的处理函数是 store 方法,在这个方法中,我们通过 Axios 库与后端接口以 Ajax 方式进行异步交互,在每次与后端接口交互之前,先要清理验证错误信息,以免污染本次处理结果。

后端的接口路由是 /post,通过 POST 方法提交表单数据后,如果处理成功,则将已发布属性 published 设置为 true,这样就可以看到发布成功的提示文案了。如果请求数据验证失败,则从后端返回的错误包中解析出错误信息赋值给对应的模型属性 errors,以便在表单模板中渲染提示用户重新输入。

最后,我们编写了一些 CSS 代码进行自定义样式设置。

编写好组件代码后,需要在 component-practice/resources/js/app.js 中注册:

Vue.component('form-component', require('./components/FormComponent.vue').default);

然后运行 npm run dev 编译刚刚调整的所有前端资源,如果是在本地开发调试,还可以运行 npm run watch 命令配合 BrowserSync 动态监听前端资源变动并自动编译和刷新浏览器页面。

这样一来,就可以在 HTML 视图中通过 form-component 标签渲染这个表单组件了。

渲染表单组件

我们在 component-practice/resources/views 目录下新建一个 form.blade.php 视图模板来渲染表单组件:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>表单组件示例</title>

    <!-- Fonts -->
    <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">

    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body class="antialiased">
    <div id="app" class="container">
        <form-component></form-component>
    </div>
    <script src="{{ asset('js/app.js') }}" type="text/javascript"></script>
</body>
</html>

注意需要将 <form-component></form-component> 组件至于 div[id=app] 容器中才能生效,另外,也不能忘了引入包含 Bootstrap CSS 框架的 app.css 和包含 Vue.js 框架的 app.js 资源文件,以上要素缺一不可。

我们在 routes/web.php 注册一个渲染该视图模板的路由:

Route::view('/form', 'form');

form-component 根目录下运行 php artisan serve 命令,就可以在浏览器中通过 http://127.0.0.1:8000/form 中访问渲染文章发布表单组件的视图页面了:

Laravel + Vue 开发表单组件

表单组件提交与验证功能

为了完成表单组件渲染、提交、验证的功能闭环,我们还需要在服务端注册一个处理表单提交的路由 /post,还是在 routes/web.php 中注册这个路由:

use \Illuminate\Http\Request;
Route::post('/post', function(Request $request) {
    $data = $request->validate([
        'title' => 'required',
        'author' => 'required',
        'content' => 'required'
    ]);

    return response()->json($data);
});

在这个路由处理闭包中,我们先是通过 $request->validate 函数基于指定规则对提交数据进行验证,如果验证不通过,会返回一个包含验证错误包的 422 响应,我们之前在编写表单组件时已经在客户端实现了对这个错误包的解析和处理逻辑。如果验证通过,则返回一个包含提交数据的 JSON 200 响应。

注:如果你对服务端验证这块细节不了解,可以参考 Laravel 验证官方文档

我们再次回到表单页面,不填写任何数据提交表单,会显示对应的验证错误信息:

Laravel + Vue 开发表单组件

而如果表单验证通过,会显示发布成功信息:

Laravel + Vue 开发表单组件

整个流程非常简单和纯净。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: 前奏篇(二):Tailwind 与 Bootstrap 的区别和使用入门

>> 下一篇: 通过 ES6 新语法对 Vue 表单组件进行面向对象重构