05.06 Ultimate Vue.js和Laravel CRUD教程

著名的JavaScript框架专家Vue.js讨论了如何创建一个执行CRUD操作的完整堆栈web应用程序。

CRUD(创建,读取,更新和删除)是数据存储的基本操作,也是您作为Laravel开发人员学习的第一件事情之一。

但是,当您将Vue.js单页应用程序添加到此堆栈的前端时会发生什么?突然之间,你必须处理异步 CRUD,因为操作现在不需要刷新页面。这需要特别注意确保数据的状态在前端后端都是一致的。

在本教程中,我将向您展示如何设置一个完整的Vue&Laravel应用程序并演示每个CRUD操作。AJAX是此体系结构的关键,因此我们将使用Axios作为HTTP客户端。我还将向您展示一些处理这种体系结构UX用户缺陷的策略。

演示应用

演示全栈应用程序允许用户创建新的“Cruds”,我决定在创造性地思考一个令人难以置信的数量后,使用陌生名称的外星生物以及从红色变为绿色和后退的能力。

Cruds显示在主页上,用户有权创建新Crud,删除它们或更新颜色。

Ultimate Vue.js和Laravel CRUD教程

在Laravel后端添加CRUD

我们将在Laravel后端开始进行CRUD操作的教程。由于Laravel CRUD是其他地方广泛涉及的主题,因此我将继续简要介绍这一部分。

总之,我们会:

  • 建立一个数据库

  • 通过使用资源控制器设置RESTful API路由

  • 定义控制器中的方法来执行CRUD操作

数据库

首先,迁移。我们的Cruds有两个属性:我们存储为文本的名称和颜色。

create_cruds_table.php

...

class CreateCrudsTable extends Migration

{

public function up()

{

Schema::create('cruds', function (Blueprint $table) {

$table->increments('id');

$table->text('name');

$table->text('color');

$table->timestamps();

});

}

...

}

...

API

现在我们设置RESTful API路由。正面的resource方法Route将自动创建我们需要的所有操作。但是,我们不需要edit,show或者store我们会排除这些。

routes/api.php

Route::resource('/cruds', 'CrudsController', [

'except' => ['edit', 'show', 'store']

]);

有了这个,我们现在可以在我们的API中使用各种端点:

Ultimate Vue.js和Laravel CRUD教程

调节器

我们现在需要在控制器中执行这些操作:

app/Http/Controllers/CrudsController.php

namespace App\\Http\\Controllers;

use App\\Crud;

use Illuminate\\Http\\Request;

use Illuminate\\Http\\Response;

use Faker\\Generator;

class CrudsController extends Controller

{

// Methods

}

我们来简单介绍一下每种方法:

create. 我们使用Faker Laravel附带的软件包随机化新Crud的名称和颜色。我们将新的Crud数据作为JSON发回。

...

public function create(Generator $faker)

{

$crud = new Crud();

$crud->name = $faker->lexify('????????');

$crud->color = $faker->boolean ? 'red' : 'green';

$crud->save();

return response($crud->jsonSerialize(), Response::HTTP_CREATED);

}

index. 我们用index方法返回全套Cruds 。在更严重的应用程序中,我们使用分页,但现在让我们保持简单。

...

public function index()

{

return response(Crud::all()->jsonSerialize(), Response::HTTP_OK);

}

update. 这个动作允许客户改变Crud的颜色。

...

public function update(Request $request, $id)

{

$crud = Crud::findOrFail($id);

$crud->color = $request->color;

$crud->save();

return response(null, Response::HTTP_OK);

}

destroy. 这是我们如何删除我们的Cruds。

...

public function destroy($id)

{

Crud::destroy($id);

return response(null, Response::HTTP_OK);

}

Vue.js App

现在为我们的Vue单页应用程序。我们将首先创建一个单一文件组件来表示我们称之为Cruds CrudComponent.vue。

Ultimate Vue.js和Laravel CRUD教程

该组件仅用于显示,并没有太多逻辑。以下是值得注意的方面:

显示的图像取决于Crud(red.png或green.png)的颜色。

有一个删除按钮,它会触发一个del点击方法,它会发出一个delete带有Crud ID 的事件。

有一个HTML选择(用于选择颜色),它触发一个update更改方法,该方法发出一个事件,其中update包含Crud的ID和所选的新颜色。

resources/assets/js/components/CrudComponent.vue

<template>

Name: {{ name | properCase }}

<select>

<option>

v-for="col in [ 'red', 'green' ]"

:value="col"

:key="col"

:selected="col === color ? 'selected' : ''"

>{{ col | properCase }}

/<option>

<button>Delete/<button>

<script>

export default {

computed: {

image() {

return `/images/${this.color}.png`;

}

},

methods: {

update(val) {

this.$emit('update', this.id, val.target.selectedOptions[0].value);

},

del() {

this.$emit('delete', this.id);

}

},

props: ['id', 'color', 'name'],

filters: {

properCase(string) {

return string.charAt(0).toUpperCase() + string.slice(1);

}

}

}

在这个项目的另一个组成部分是App.js。这就是所有有趣的逻辑发生的地方,所以我们将逐步完成这一步。

我们从模板开始。这有以下工作:

  • 用crud-component上面讨论的组件显示我们的Cruds 。

  • 循环访问Crud对象(在数组中cruds),每个映射到一个实例crud-component。我们通过对组件作为道具经过一个CRUD的所有属性和设置的听众update,并delete从组件来的事件。

  • 我们也有一个Add按钮,通过create点击触发一个方法来创建新的Cruds 。

resources/assets/js/components/App.vue

<template>

Cruds

<crud-component>

v-for="crud in cruds"

v-bind="crud"

:key="crud.id"

@update="update"

@delete="del"

>

/<crud-component>

<button>Add/<button>

下面是script从App.js。我们也来谈谈这个:

  • 我们从一个Crud创建用于表示我们的Crud的新对象开始。每个人都有一个ID,颜色和名称。

  • 我们导入相邻 CrudComponent

  • 组件定义包含数组cruds作为数据属性。我还为每个CRUD操作存储了方法,这些操作将在下一节中介绍。

resources/assets/js/components/App.vue

<template>.../<template>

<script>

function Crud({ id, color, name}) {

this.id = id;

this.color = color;

this.name = name;

}

import CrudComponent from './CrudComponent.vue';

export default {

data() {

return {

cruds: []

}

},

methods: {

create() {

// To do

},

read() {

// To do

},

update(id, color) {

// To do

},

del(id) {

// To do

}

},

components: {

CrudComponent

}

}

使用AJAX从前端触发CRUD

由于这是数据库所在的位置,因此全栈应用程序中的所有CRUD操作都将在后端执行。但是,CRUD操作的触发通常会发生在前端。

因此,HTTP客户端(可以通过互联网在我们的前端和后端之间进行通信的东西)在这里很重要。Axios是一个很棒的HTTP客户端,它预装了默认的Laravel前端。

让我们再看看我们的资源表,因为每个AJAX调用都需要定位到相关的API端点:

Ultimate Vue.js和Laravel CRUD教程

我们从这个read方法开始。这个方法负责从后端检索我们的Cruds,并且将针对index我们的Laravel控制器的行为,从而使用GET endpoint/api/cruds。

我们可以设置一个GET调用window.axios.get,因为window在默认的Laravel前端设置中,Axios库已经作为对象的属性。

Axios的方法,例如get,post等等都会返回一个承诺。我们then用一个回调链接一个方法来访问响应。解析的对象可以被解构以允许方便地访问data回调中的属性,这是AJAX响应的主体。

resources/assets/js/components/App.vue

...

methods() {

read() {

window.axios.get('/api/cruds').then(({ data }) => {

// console.log(data)

});

},

...

}

/*

Sample response:

[

{

"id": 0,

"name": "ijjpfodc",

"color": "green",

"created_at": "2018-02-02 09:15:24",

"updated_at": "2018-02-02 09:24:12"

},

{

"id": 1,

"name": "wjwxecrf",

"color": "red",

"created_at": "2018-02-03 09:26:31",

"updated_at": "2018-02-03 09:26:31"

}

]

*/

正如你所看到的,Cruds是以JSON数组的形式返回的。Axios会自动分析JSON并为我们提供JavaScript对象,这很好。让我们在回调中遍历这些内容,然后使用我们的Crud工厂函数创建新的Cruds ,然后将它们推送到cruds数组数据属性即this.cruds.push(...)。

resources/assets/js/components/App.vue

...

methods() {

read() {

window.axios.get('/api/cruds').then(({ data }) => {

data.forEach(crud => {

this.cruds.push(new Crud(crud));

});

});

},

},

...

created() {

this.read();

}

注意:我们需要read在应用程序加载时以编程方式触发该方法。我们从created钩子上做到了这一点,但效果不是很好。read完全摆脱该方法会更好,只需在第一次加载时将应用程序的初始状态内联到文档头中即可。

完成后,我们现在可以在加载时在应用中看到Cruds:

Ultimate Vue.js和Laravel CRUD教程

更新(和同步状态)

该update行动要求我们发送表单数据,即color控制器知道要更新什么。Crud的ID在终点中给出。

这是讨论我在本文开头提到的问题的好时机:在全栈应用程序中,您必须确保数据的状态在前端和后端都一致。

在该update方法的情况下,我们可以在AJAX调用之前立即更新前端应用程序中的Crud对象,因为我们已经知道新状态。

但是,在AJAX调用完成之前,我们不会执行此更新。为什么?原因是该操作可能因某种原因失败:互联网连接可能会丢失,更新后的值可能会被数据库拒绝或其他原因。

如果我们等到服务器在更新前端状态之前做出响应,我们可以确定该操作已成功完成,并且前端和后端数据已同步。

resources/assets/js/components/App.vue

methods: {

read() {

...

},

update(id, color) {

window.axios.put(`/api/cruds/${id}`, { color }).then(() => {

// Once AJAX resolves we can update the Crud with the new color

this.cruds.find(crud => crud.id === id).color = color;

});

},

...

}

你可能会认为它的糟糕的用户体验等待AJAX解决,然后在不需要的时候显示更改的数据,但是我认为用户误导用户认为已经完成更改会更糟糕,实际上,我们并没有不知道它是否完成。

创建和删除

既然您已经理解了架构的关键点,那么您将能够理解这些最后两个操作,而无需我的评论:

resources/assets/js/components/App.vue

methods: {

read() {

...

},

update(id, color) {

...

},

create() {

window.axios.get('/api/cruds/create').then(({ data }) => {

this.cruds.push(new Crud(data));

});

},

del(id) {

window.axios.delete(`/api/cruds/${id}`).then(() => {

let index = this.cruds.findIndex(crud => crud.id === id);

this.cruds.splice(index, 1);

});

}

}

加载指标并禁用交互

如您所知,我们的CRUD操作是异步的,因此在等待AJAX呼叫到达服务器时,服务器会作出响应并接收响应时会有小的延迟。

为了改进用户体验,在我们等待当前操作解决的同时,拥有某种视觉加载指示器并禁用任何交互性会很好。这可以让用户知道正在发生的事情,并且可以让他们确定数据的状态。

对于Vue.js加载状态有一些很好的插件,但我只是想在这里做一些快速和肮脏的事情:在AJAX进行时,我将覆盖整个屏幕,div在应用程序的顶部半透明。这将用一块石头杀死上述两只鸟。

resources/views/index.blade.php

为此,我们将mute在AJAX正在进行时将布尔值从false 切换到true,并使用此值来显示/隐藏div。

resources/assets/js/components/App.vue

export default {

data() {

return {

cruds: [],

mute: false

}

},

...

}

下面是我们如何实现的触发mute的update方法。当该方法被调用时,mute被设置为true。当承诺解决时,AJAX已完成,因此用户再次与应用程序交互是安全的,因此我们将其设置mute为false。

resources/assets/js/components/App.vue

update(id, color) {

this.mute = true;

window.axios.put(`/api/cruds/${id}`, { color }).then(() => {

this.cruds.find(crud => crud.id === id).color = color;

this.mute = false;

});

},

您需要在每个CRUD方法中实现相同的功能,但为简洁起见,我不会在此显示。

为了使我们的加载指示器标记和CSS,我们

直接在我们的mount元素上添加元素

从内联样式中可以看到,当类on添加时

,它将完全覆盖应用程序,添加灰色调并防止任何点击事件到达按钮并选择:

resources/views/index.blade.php

<title>Cruds/<title>

<style>

html, body {

margin: 0;

padding: 0;,

height: 100%;

width: 100%;

background-color: #d1d1d1

}

#mute {

position: absolute;

}

#mute.on {

opacity: 0.7;

z-index: 1000;

background: white;

height: 100%;

width: 100%;

}

最后一块难题是on通过使用一个watch值来切换课程,mute每次mute更改时都会调用此方法:

export default {

...

watch: {

mute(val) {

document.getElementById('mute').className = val ? "on" : "";

}

}

}

完成后,您现在可以使用带有加载指示器的全功能Vue / Laravel CRUD应用程序。这里又一次充满荣耀:

Ultimate Vue.js和Laravel CRUD教程

不要忘记抓住这个GitHub仓库中的代码,如果您有任何想法或问题,请留下评论!

"


分享到:


相關文章: