建立一个新应用:javascript
$ laravel new vue-to-do $ cd vue-to-do
建立 Task 相关:php
$ php artisan make:model Task -mc Model created successfully. Created Migration: 2017_05_01_050911_create_tasks_table Controller created successfully.
配置数据库:css
// /.env DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=vue_todo DB_USERNAME=root DB_PASSWORD=
编辑迁移文件:html
/database/migrations/2017_05_01_050911_create_tasks_table.php Schema::create('tasks', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->text('description'); $table->timestamps(); });
执行迁移:前端
$ php artisan migrate
路由:vue
/routes/web.php Route::get('/tasks','TaskController@index'); Route::post('/tasks','TaskController@store');
控制器:java
/app/Http/Controllers/TaskController.php <?php namespace App\Http\Controllers; use App\Task; use Illuminate\Http\Request; class TaskController extends Controller { /** * 显示与建立任务列表 * @return [Response] [view] */ public function index() { $tasks = Task::all(); return view('tasks.index', compact('tasks')); } /** * 保存任务列表 * @return [Response] [message] */ public function store() { $this->validate(request(), [ 'name' => 'required', 'description' => 'required' ]); Task::forceCreate(request('name', 'description')); return ['message' => '任务建立成功']; } }
首先定义视图:mysql
/resources/views/tasks/index.blade.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue-To-Do-List</title> </head> <body> <div id="app" class="container"> @if (count($tasks)) <table class="table"> <thead> <tr> <th>#</th> <th>任务名</th> <th>描述</th> </tr> </thead> <tbody> @foreach ($tasks as $task) <tr> <th>{{ $task['id']}}</th> <td>{{ $task['name'] }}</td> <td>{{ $task['description'] }}</td> </tr> @endforeach </tbody> </table> @endif <form method="POST" action="/tasks" @submit.prevent="onSubmit"> <fieldset class="form-group"> <label for="name">任务名</label> <input type="text" class="form-control" id="name" name="name" v-model="name"> </fieldset> <fieldset class="form-group"> <label for="description">任务描述</label> <input type="text" class="form-control" id="description" name="description" v-model="description"> </fieldset> <button type="submit" class="btn btn-primary">建立</button> </form> </div> <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/vue/2.2.6/vue.js"></script> <script src="https://cdn.bootcss.com/axios/0.16.1/axios.js"></script> <script type="text/javascript" src="/js/app.js"></script> </body> </html>
为了阻止表单的提交,能够使用 prevent
修饰符,至关于调用 Event.preventDefault()
方法。ios
前端业务逻辑:laravel
/public/js/app.js Vue.prototype.$http = axios; var vm = new Vue({ el: '#app', data: { name:'', description:'' }, methods: { onSubmit(){ this.$http.post('/tasks',this.$data) } } })
这里使用了以前介绍的 axios
包,其中,$data
为实例的 data 对象。在这里至关于:
this.$http.post('/tasks',{ name: this.name, description: this.description })
基本的效果以下:
以前只实现了正确提交的功能。接下来实现错误提交的状况。
axios
的 post
请求的基本方法以下:
axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) // 成功 .then(function (response) { console.log(response); }) // 失败 .catch(function (error) { console.log(error); });
假如提交了一个空的表单,后台会返回错误消息,咱们能够经过 error.response.data
来访问。好比
data: { name:'', description:'', errors:{} }, methods: { onSubmit(){ this.$http.post('/tasks',this.$data) .catch(error => this.errors = error.response.data); } }
为了方便操做,能够将其封装成类:
Vue.prototype.$http = axios; class Errors { /** * 初始化 */ constructor(){ this.errors = {} } /** * 保存错误信息 */ record(errors){ this.errors = errors; } } var vm = new Vue({ el: '#app', data: { name:'', description:'', errors:new Errors() }, methods: { onSubmit(){ this.$http.post('/tasks',this.$data) .catch(error => this.errors.record = error.response.data); } } })
在控制台中查看对应的 errors
实例:
也就是说,能够经过 errors[name][0]
的方式来访问错误信息,将其写成方法:
get(field) { if (this.errors[field]) { return this.errors[field][0]; } }
页面中就能够显示错误消息了:
<fieldset class="form-group"> <label for="name">任务名</label> <input type="text" class="form-control" id="name" v-model="name"> <small class="text-danger" v-text="errors.get('name')"></small> </fieldset> <fieldset class="form-group"> <label for="description">任务描述</label> <input type="text" class="form-control" id="description" v-model="description"> <small class="text-danger " v-text="errors.get('description')"></small> </fieldset>
效果以下:
接着,增长条件判断,以决定是否显示错误信息的页面:
<small class="text-danger" v-if="errors.has('name')" v-text="errors.get('name')"></small> <small class="text-danger" v-if="errors.has('description')" v-text="errors.get('description')"></small>
对应的方法:
/** * 判断属性是否存在 * @param {string} field */ has(field){ return this.errors.hasOwnProperty(field); }
当存在错误消息的时候,不容许用户再次提交:
<button type="submit" class="btn btn-primary" :disabled="errors.any()">建立</button>
对应的方法:
any(){ return Object.keys(this.errors).length > 0; }
最后,用户从新输入时,应当清空错误消息:
<form method="POST" action="/tasks" @submit.prevent="onSubmit" @keydown="errors.clear($event.target.name)">
对应方法:
clear(field){ if (field) { delete this.errors[field]; return; } this.errors = {}; }
附录: