七、添加 Vue 表单
在本章中,您将使用v-model
和v-bind
创建表单。您将学习在将表单数据发送到服务器之前在客户端验证表单。您将使用基本元素创建表单,绑定动态值并使用修饰符修改输入元素的行为。您还将学习使用vee-validate
插件验证表单并将其应用于 Nuxt 应用。在本章中,学习和理解如何将v-model
和v-bind
与 Vue 表单一起使用非常重要,因为我们将在接下来的章节中使用表单,例如第 10 章、添加 Vuex 商店、第 12 章、创建用户登录和 API 验证中。
我们将在本章中介绍的主题如下:
- 理解
v-model
- 使用基本数据绑定验证表单
- 创建动态值绑定
- 使用
vee-validate
验证表格 - 在 Nuxt 中应用 Vue 表单
理解 v 模型
v-model
是一个 Vue 指令(自定义内置的 Vue HTML 属性),允许我们在表单的input
、textarea
和select
元素上创建双向绑定。可以将表单输入与 Vue 数据绑定,以便在用户与输入字段交互时更新数据。v-model
将始终跳过您在表单元素上设置的初始值,但将 Vue 数据视为真相的来源。因此,您应该在 Vue 端的data
选项或函数中声明初始值。
v-model
将根据输入类型选择适当的方式更新元素,这意味着如果您在带有type="text"
的表单输入中使用它,它将使用value
作为属性,input
作为事件为您执行双向绑定。在接下来的章节中,让我们看一下该指令下的内容。
在 text 和 textarea 元素中使用 v-model
还记得我们在第 5 章、添加 Vue 组件中通过v-model
实现的创建自定义输入组件的双向绑定吗?在该章的创建自定义输入组件一节中,我们了解到输入的v-model
语法—<input v-model="username">
是以下内容的简写:
<input
v-bind:value="username"
v-on:input="username = $event.target.value"
>
这个文本input
元素在幕后绑定了value
属性,该属性从处理程序username
获取值,该处理程序从input
事件获取其值。因此,自定义文本输入组件也必须始终在model
属性中使用value
属性和input
事件,如下所示:
Vue.component('custom-input', {
props: {
value: String
},
model: {
prop: 'value',
event: 'input'
},
template: `<input v-on:input="$emit('input', $event.target.value)">`,
})
这只是因为v-model
输入的性质是由v-bind:value
和v-on:input
组成的。在textarea
元素中使用v-model
指令时也是如此,如下例所示:
<textarea v-model="message"></textarea>
此v-model``textarea
元素是以下内容的简写:
<textarea
v-bind:value="message"
v-on:input="message = $event.target.value"
></textarea>
这个textarea
输入元素在幕后绑定了value
属性,该属性从处理程序message
获取值,该处理程序从input
事件获取其值。因此,自定义textarea
组件也必须始终符合v-model``textarea
元素的性质,使用value
属性中的value
属性和input
事件,如下所示:
Vue.component('custom-textarea', {
props: {
value: null
},
model: {
prop: 'value',
event: 'input'
}
})
简言之,v-model
textinput
元素和v-model``textarea
输入元素总是将value
属性与处理程序绑定,以获取输入事件上的新值,通过采用相同的属性和事件,自定义输入组件也必须如此。那么复选框和单选按钮元素中的v-model
呢?让我们在下一节深入探讨它们。
在复选框和单选元素中使用 v 型
另一方面,v-model``checkbox
和radio
按钮输入元素总是将checked
属性与在change
事件中更新的布尔值绑定,如下例所示:
<input type="checkbox" v-model="subscribe" value="yes" name="subscribe">
前面代码片段中的v-model``checkbox
输入元素实际上是以下内容的简写:
<input
type="checkbox"
name="subscribe"
value="yes"
v-bind:checked="false"
v-on:change="subscribe = $event.target.checked"
>
因此,自定义复选框输入元素也必须始终符合v-model
复选框输入元素的性质(如前面的代码块所示),方法是采用model
属性中的checked
属性和change
事件,如下所示:
Vue.component('custom-checkbox', {
props: {
checked: Boolean,
},
model: {
prop: 'checked',
event: 'change'
}
})
同样适用于v-model
单选按钮输入元素,如下所示:
<input type="radio" v-model="answer" value="yes" name="answer">
前面的v-model
元素是以下内容的另一个缩写:
<input
type="radio"
name="answer"
value="yes"
v-bind:checked="answer == 'yes'"
v-on:change="answer = $event.target.value"
>
因此,自定义单选按钮输入元素也必须始终符合v-model
元素的性质,如下所示:
Vue.component('custom-radio', {
props: {
checked: String,
value: String
},
model: {
prop: 'checked',
event: 'change'
}
})
简而言之,由于v-model``checkbox
和radio
按钮输入元素总是绑定value
属性,并在change
事件中更新,因此必须采用相同属性和事件的自定义输入组件。现在,让我们来看看 Apple T5 如何在下一节中的元素 T6 中工作。
在“选择图元”中使用 v 模型
毫不奇怪,v-modelselect
输入元素总是将value
属性与处理程序绑定,以获取其在change
事件上的选定值,如下例所示:
<select
v-model="favourite"
name="favourite"
>
//...
</select>
前面的v-model``checkbox
输入元素只是以下内容的另一个缩写:
<select
v-bind:value="favourite"
v-on:change="favourite = $event.target.value"
name="favourite"
>
//...
</select>
因此,自定义的checkbox
输入元素也必须始终符合v-model
元素的性质,使用value
属性和model
属性中的change
事件,如下所示:
Vue.component('custom-select', {
props: {
value: String
},
model: {
prop: 'value',
event: 'change'
}
})
如您所见,v-model
是v-bind
之上的语法糖,它将值绑定到标记,v-on
更新用户输入事件的数据,可以是change
或input
事件。简而言之,v-model
将v-bind
和v-on
结合在一起,但作为 Vue/Nuxt 应用开发人员,理解语法背后的含义很重要。
You can find the examples we've covered in this section in /chapter-7/vue/html/
in our GitHub repository.
既然您已经发现了v-model
指令在表单的输入元素中是如何工作的,那么让我们在表单上使用这些v-model
元素,并在下一节中验证它们。
使用基本数据绑定验证表单
表格是收集信息的文件。HTML<form>
元素是一种可以从 web 用户处收集数据或信息的表单。此元素需要其中的<input>
元素来指定我们要收集的数据。但在接受数据之前,我们通常希望验证和过滤数据,以便从用户那里获得真实和正确的数据。
Vue 允许我们轻松地验证来自v-model
输入元素的数据,因此让我们从单文件组件(SFC)Vue 应用和网页包开始,您在第 5 章、添加 Vue 组件以及使用网页包编译单文件组件部分了解了这一点。首先,我们将创建一个非常简单的表单,其中包含一个submit
按钮和用于在<template>
块中显示错误消息的标记,如下所示:
// src/components/basic.vue
<form v-on:submit.prevent="checkForm" action="/" method="post">
<p v-if="errors.length">
<b>Please correct the following error(s):</b>
<ul>
<li v-for="error in errors">{{ error }}</li>
</ul>
</p>
<p>
<input type="submit" value="Submit">
</p>
</form>
稍后我们将在<form>
中添加其余的输入元素。现在,让我们建立基本结构并了解我们需要什么。默认情况下,我们使用v-on:submit.prevent
阻止浏览器发送表单数据,因为我们将在<script>
块的 Vue 实例中使用checkForm
方法处理提交:
// src/components/basic.vue
export default {
data () {
return {
errors: [],
form: {...}
}
},
methods:{
checkForm (e) {
this.errors = []
if (!this.errors.length) {
this.processForm(e)
}
},
processForm (e) {...}
}
}
在 JavaScript 方面,我们定义了一个数组来保存验证过程中可能出现的错误。checkForm
逻辑验证我们将在本节后面添加的必需字段。如果必填字段未通过验证,则我们将错误消息推送到errors
。当表单填写正确并且/或者没有发现错误时,它将被传递到processForm
逻辑,在那里我们可以在将表单数据发送到服务器之前进一步处理表单数据。
验证文本元素
让我们首先为单行文本添加一个<input>
元素:
// src/components/basic.vue
<label for="name">Name</label>
<input v-model="form.name" type="text">
export default {
data () {
return {
form: { name: null }
}
},
methods:{
checkForm (e) {
this.errors = []
if (!this.form.name) {
this.errors.push('Name required')
}
}
}
}
在<script>
块中,我们在data
函数中定义了一个name
属性,该属性保存初始null
值,并将根据<input>
元素的input
事件进行更新。当您点击submit
按钮时,我们验证if
条件块中的name
数据;如果没有提供数据,则我们push
将错误消息发送到errors
。
验证 textarea 元素
我们要添加的下一个元素是多行文本的<textarea>
,其工作方式与<input>
相同:
// src/components/basic.vue
<label for="message">Message</label>
<textarea v-model="form.message"></textarea>
export default {
data () {
return {
form: { message: null }
}
},
methods:{
checkForm (e) {
this.errors = []
if (!this.form.message) {
this.errors.push('Message required')
}
}
}
}
在<script>
块中,我们在data
函数中定义了一个message
属性,该属性保存初始null
值,并将根据<textarea>
元素的input
事件进行更新。当您点击submit
按钮时,我们验证if
条件块中的message
数据;如果没有提供数据,则我们push
将错误消息发送到errors
。
验证复选框元素
下一个元素是一个复选框<input>
元素,它将保存默认的布尔值:
// src/components/basic.vue
<label class="label">Subscribe</label>
<input type="checkbox" v-model="form.subscribe">
export default {
data () {
return {
form: { subscribe: false }
}
},
methods:{
checkForm (e) {
this.errors = []
if (!this.form.subscribe) {
this.errors.push('Subscription required')
}
}
}
}
我们还将添加以下绑定到同一数组的多个复选框<input>
元素,即books: []
:
// src/components/basic.vue
<input type="checkbox" v-model="form.books" value="On the Origin of Species">
<label for="On the Origin of Species">On the Origin of Species</label>
<input type="checkbox" v-model="form.books" value="A Brief History of Time">
<label for="A Brief History of Time">A Brief History of Time</label>
<input type="checkbox" v-model="form.books" value="The Selfish Gene">
<label for="The Selfish Gene">The Selfish Gene</label>
export default {
data () {
return {
form: { books: [] }
}
},
methods:{
checkForm (e) {
this.errors = []
if (this.form.books.length === 0) {
this.errors.push('Books required')
}
}
}
}
在<script>
块中,我们在data
函数中定义了一个subscribe
属性,该属性保存初始布尔值false
,并将在复选框<input>
元素的change
事件中更新。当您点击submit
按钮时,我们验证if
条件块中的subscribe
数据;如果未提供数据或为false
,则我们push
将错误消息发送至errors
。
对于多个 checkbox<input>
元素,我们也会定义一个books
属性,该属性保存初始空数组,并将在 checkbox<input>
元素的change
事件中更新。验证if
条件块中的books
数据;如果其长度为0
,则我们push
将错误消息发送至errors
。
验证无线电元件
下一个元素是绑定到相同属性名的多个单选按钮<input>
元素,即gender
:
// src/components/basic.vue
<label for="male">Male</label>
<input type="radio" v-model="form.gender" value="male">
<label for="female">Female</label>
<input type="radio" v-model="form.gender" value="female">
<label for="other">Other</label>
<input type="radio" v-model="form.gender" value="other">
export default {
data () {
return {
form: { gender: null }
}
},
methods:{
checkForm (e) {
this.errors = []
if (!this.form.gender) {
this.errors.push('Gender required')
}
}
}
}
在<script>
块中,我们在data
函数中定义了一个gender
属性,该属性保存初始null
值,并将在所选<input>
单选按钮元素的change
事件中更新。当您点击submit
按钮时,我们验证if
条件块中的gender
数据。如果没有提供数据,则我们push
将错误消息发送到errors
。
验证所选元素
下一个元素是单个<select>
元素和多个<option>
元素,如下所示:
// src/components/basic.vue
<select v-model="form.favourite">
<option disabled value="">Please select one</option>
<option value="On the Origin of Species">On the Origin of
Species</option>
<option value="A Brief History of Time">A Brief History of Time</option>
<option value="The Selfish Gene">The Selfish Gene</option>
</select>
export default {
data () {
return {
form: { favourite: null }
}
},
methods:{
checkForm (e) {
this.errors = []
if (!this.form.favourite) {
this.errors.push('Favourite required')
}
}
}
}
最后一个是多个<select>
元素,其中多个<option>
元素绑定到同一个Array
,即favourites: []
:
// src/components/basic.vue
<select v-model="form.favourites" multiple >
<option value="On the Origin of Species">On the Origin of
Species</option>
<option value="A Brief History of Time">A Brief History of Time</option>
<option value="The Selfish Gene">The Selfish Gene</option>
</select>
export default {
data () {
return {
form: { favourites: [] }
}
},
methods:{
checkForm (e) {
this.errors = []
if (this.form.favourites.length === 0) {
this.errors.push('Favourites required')
}
}
}
}
在<script>
块中,我们在data
函数中定义了一个favourites
属性,该属性保存初始null
值,并将根据<select>
元素的change
事件进行更新。当您点击submit
按钮时,我们验证if
条件块中的favourites
数据。如果没有提供数据,则我们push
将错误消息发送到errors
。对于多个<select>
元素,我们也可以通过定义一个favourites
属性来执行相同的操作,该属性保存初始空数组,并将在<select>
元素的change
事件中进行更新。验证if
条件块中的favourites
数据;如果其长度为0
,则我们将错误消息推送到errors
。
然后我们将使用processForm
逻辑完成此表单,只有在checkForm
逻辑中没有发现错误时才会调用此表单。我们使用 Node.js 包qs
对this.form
对象进行字符串化,以便我们可以将数据以以下格式发送到服务器:
name=John&message=Hello%20World&subscribe=true&gender=other
让我们用 npm 安装qs
:
$ npm i qs
然后我们可以按如下方式使用它:
import axios from 'axios'
import qs from 'qs'
processForm (e) {
var data = qs.stringify(this.form)
axios.post('../server.php', data)
.then((response) => {
// success callback
}, (response) => {
// error callback
})
}
我们使用axios
发送数据并从服务器获取响应(通常为 JSON 格式),然后您可以对响应数据进行处理,例如在服务器端显示“成功”或“失败”消息。
For more information about qs
, visit https://www.npmjs.com/package/qs, and for axios
, please visit https://github.com/axios/axios.
You can find the preceding example app in /chapter-7/vue/webpack/
in our GitHub repository.
但是,我们还没有完全完成,因为我们有时可能希望将动态值绑定到表单输入,而不是从v-model
获取默认值。例如,在我们的示例应用中,我们仅通过单个复选框<input>
元素获取subscribe
属性的布尔值,但我们希望使用带有yes
或no
的字符串值。在下一节中,我们将探讨如何更改默认值。
创建动态值绑定
在上一节的示例应用中,我们单独使用v-model
获取radio
、checkbox
和select
选项的字符串或布尔值。我们可以使用true-value
、false-value
和v-bind
更改此默认值。让我们潜水吧。
替换布尔-复选框元素
我们可以使用true-value
和false-value
将自定义值绑定到单个checkbox
元素。例如,我们可以绑定yes
值,用true-value
替换默认true
布尔值,用false-value
替换默认false
布尔值:
// src/components/dynamic-values.vue
<input
type="checkbox"
v-model="form.subscribe"
true-value="yes"
false-value="no"
>
export default {
data () {
return {
form: { subscribe: 'no' }
}
},
methods:{
checkForm (e) {
this.errors = []
if (this.form.subscribe !== 'yes') {
this.errors.push('Subscription required')
}
}
}
}
现在,当您将subscribe
输入的值发送到服务器时,您会得到yes
或no
的响应。在<script>
块中,我们现在将no
声明为subscribe
属性的初始值,并在if
条件块中验证它,以确保当您点击submit
按钮时它始终是yes
,否则我们将错误消息推到errors
。
用动态属性替换字符串–单选元素
对于单选按钮<input>
元素,我们可以使用v-bind
将其值绑定到 Vue 实例中的动态属性:
// src/components/dynamic-values.vue
<input type="radio" v-model="form.gender" v-bind:value="gender.male">
export default {
data () {
return {
gender: {
male: 'm',
female: 'f',
other: 'o',
},
form: { gender: null }
}
}
}
现在,当选中此单选按钮且验证与之前相同时,您将获得m
。
用对象替换字符串–选择选项元素
我们也可以使用v-bind
非字符串值,例如Object
来进行表单输入。请参见以下示例:
// src/components/dynamic-values.vue
<select v-model="form.favourite">
<option v-bind:value="{ title: 'On the Origin of Species' }">On
the Origin of Species</option>
</select>
export default {
data () {
return {
form: {
favourite: null
}
}
}
}
现在选择此选项后,typeof this.favourite
得到object
,this.favourite.title
得到On the Origin of Species
。验证逻辑没有变化。
我们还可以使用动态值和v-for
动态呈现<option>
元素:
// src/components/dynamic-values.vue
<select v-model="form.favourites" name="favourites_array[]" multiple >
<option v-for="book in options.books" v-bind:value="book.value">
{{ book.text }}
</option>
</select>
data () {
return {
form: { favourites: [] },
options: {
books: [
{ value: { title: 'On the Origin of Species' }, text: 'On the
Origin of Species'},
{ value: { title: 'A Brief History of Time' }, text: 'A Brief
History of Time'},
{ value: { title: 'The Selfish Gene' }, text: 'The Selfish Gene'}
]
}
}
}
现在我们不必再硬编码<option>
元素了。我们可以从其他地方提取books
数据,比如 API。
除了绑定动态值以形成输入外,我们还可以修改输入元素上的v-model
的默认行为。例如,我们可以在数据上使用change
事件,而不是将输入与数据同步。让我们在下一个主题中了解如何做到这一点。
使用修饰语
Vue 提供了这三个修饰符,.lazy
、.number
和.trim
,我们可以使用它们与v-model
一起更改默认事件或向表单输入添加额外功能。让我们潜水吧。
添加。懒惰
我们可以使用.lazy
和v-model
将input
事件更改为<input>
和<textarea>
元素上的change
事件。请参见以下示例:
// src/components/modifiers.vue
<input v-model.lazy="form.name" type="text">
现在与数据的输入在change
之后同步,而不是默认的input
事件。
添加.编号
我们可以使用.number
和v-model
在<input>
元素上用type="number"
将string
的默认类型转换更改为number
。请参见以下示例:
// src/components/modifiers.vue
<input v-model.number="form.age" type="number">
现在,您可以在没有.number
的情况下,为typeof this.form.age
获得number
而不是string
。
添加。修剪
我们可以使用.trim
和v-model
来删除用户输入中的空白。请参见以下示例:
// src/components/modifiers.vue
<textarea v-model.lazy.trim="form.message"></textarea>
现在,来自用户的文本将自动修剪。文本开头和结尾的任何额外空白都将被删除。
虽然编写自定义验证逻辑是可能的,但是已经有一个很好的插件可以帮助轻松验证输入并显示相应的错误。该插件称为 VeeValidate,是一个基于模板的 Vue 验证框架。让我们在下一节中了解如何利用此插件。
使用 VeeValidate 验证表单
使用 VeeValidate,我们将使用 VeeValidate 的组件来验证 HTML 表单和 Vue 的作用域插槽以公开错误消息。例如,这是一个我们已经熟悉的v-model
输入元素:
<input v-model="username" type="text" />
如果要使用 VeeValidate 验证,只需使用<ValidationProvider>
组件包装输入:
<ValidationProvider name="message" rules="required" v-slot="{ errors }">
<input v-model="username" name="username" type="text" />
<span>{{ errors[0] }}</span>
</ValidationProvider>
通常,我们使用<ValidationProvider>
组件来验证<input>
元素。我们可以使用rules
属性将验证规则附加到此组件,并使用v-slot
指令显示错误。让我们通过以下步骤了解如何利用此插件加快验证过程:
- 使用 npm 安装 VeeValidate:
$ npm i vee-validate
- 在
/src/
目录中创建一个.js
文件,并使用 VeeValidate 中的extend
功能添加规则:
// src/vee-validate.js
import { extend } from 'vee-validate'
import { required } from 'vee-validate/dist/rules'
extend('required', {
...required,
message: 'This field is required'
})
VeeValidate 在单独的捆绑包中提供了许多内置的验证规则,如required
、email
、min
、regex
等,因此我们可以导入我们的应用只需要的特定规则。因此在前面的代码中,我们导入了required
规则并通过extend
函数进行安装,然后在message
属性中添加自定义消息。
- 将
/src/vee-validate.js
导入启动 Vue 实例的主入口文件:
// src/main.js
import Vue from 'vue'
import './vee-validate'
- 将
ValidationProvider
组件本地导入页面,并开始验证该页面上的输入字段:
// src/components/vee-validation.vue
<ValidationProvider name="name" rules="required|min:3" v-slot="{ errors }">
<input v-model.lazy="name" type="text" name="name">
<span>{{ errors[0] }}</span>
</ValidationProvider>
import { ValidationProvider } from 'vee-validate'
export default {
components: {
ValidationProvider
}
}
我们也可以在/src/main.js
或/src/plugins/vee-validate.js
中全局注册ValidationProvider
:
import Vue from 'vue'
import { ValidationProvider, extend } from 'vee-validate'
Vue.component('ValidationProvider', ValidationProvider)
但是,如果你不需要在应用的每个页面上都使用这个组件,那么这可能不是一个好主意。因此,如果您只需要在页面上使用它,请在本地导入它。
- 本地导入
ValidationObserver
组件,并将passes
对象添加到v-slot
指令中。因此,让我们从步骤 4重构JavaScript 代码,如下所示:
// src/components/vee-validation.vue
<ValidationObserver v-slot="{ passes }">
<form v-on:submit.prevent="passes(processForm)" novalidate="true">
//...
<input type="submit" value="Submit">
</form>
</ValidationObserver>
import {
ValidationObserver,
ValidationProvider
} from 'vee-validate'
export default {
components: {
ValidationObserver,
ValidationProvider
},
methods:{
processForm () {
console.log('Posting to the server...')
}
}
}
在提交之前,我们使用<ValidationObserver>
组件包装<form>
元素来判断它是否有效。我们还在<ValidationObserver>
组件的作用域插槽的对象中使用passes
属性,用于防止表单在无效时提交。然后我们将我们的processForm
方法传递给表单元素上v-on:submit
事件中的passes
函数。如果表单无效,则不会调用我们的processForm
方法。
就这样。我们完了。您可以看到,methods
属性中的v-on:submit
事件不再需要checkForm
方法,因为 VeeValidate 已经为我们完成了验证元素的繁重工作,现在我们的 JavaScript 代码缩短了。我们只需要用<ValidationProvider>
和<ValidationObserver>
组件包装输入字段。
If you want to find out more about the Vue slots and VeeValidate, please visit the following links:
- https://logaretm.github.io/vee-validate/ 用于验证
- https://vuejs.org/v2/guide/components-slots.html 用于 Vue 插槽
You can find the example of our preceding Vue app in /chapter-7/vue/cli/
in our GitHub repository.
接下来,我们将在下一节中了解如何在 Nuxt 应用中应用 VeeValidate。
将自定义验证应用于 Nuxt 应用
让我们将自定义验证应用于我们已经拥有的示例网站中的联系人页面。您可能已经注意到,现有的联系人窗体已经安装了来自基础的验证(ZURB)。使用 Foundation 的表单验证是另一种增强 HTML 表单验证的好方法。
If you are interested in knowing more about Foundation, you can find out more from their official guide at https://foundation.zurb.com/sites/docs/abide.html.
但是,如果我们想使用 VeeValidate 进行自定义验证(我们刚刚学习了在 Vue 应用中使用 VeeValidate),那么让我们通过以下步骤安装并设置 Nuxt 所需的内容:
- 通过 npm 安装 VeeValidate:
$ npm i vee-validate
- 在
/plugins/
目录中创建一个插件文件,并添加我们需要的规则,如下所示:
// plugins/vee-validate.js
import { extend } from 'vee-validate'
import {
required,
email
} from 'vee-validate/dist/rules'
extend('required', {
...required,
message: 'This field is required'
})
extend('email', {
...email,
message: 'This field must be a valid email'
})
此文件中的所有内容都与我们在 Vue 应用中创建的文件相同。
- 在 Nuxt 配置文件的
plugins
选项中包括插件路径:
// nuxt.config.js
plugins: [
'~/plugins/vee-validate'
]
- 在 Nuxt 配置文件的
build
选项中为/vee-validate/dist/rules.js
文件添加异常:
// nuxt.config.js
build: {
transpile: [
"vee-validate/dist/rules"
],
extend(config, ctx) {}
}
在 Nuxt 中,/node_modules/
文件夹默认被排除在传输之外,使用vee-validate
时会出现读取Unexpected token export
的错误,所以在运行 Nuxt app 之前必须添加/vee-validate/dist/rules.js
进行传输。
- 导入
ValidationObserver
和ValidationProvider
组件,就像我们为 Vue 应用所做的那样:
// pages/contact.vue
import {
ValidationObserver,
ValidationProvider
} from 'vee-validate'
export default {
components: {
ValidationObserver,
ValidationProvider
}
}
- 从
<form>
元素中删除 Foundation 的data-abide
属性,但用<ValidationObserver>
组件将其包装,并用passes
和processForm
方法将submit
事件绑定到<form>
元素,如下所示:
// pages/contact.vue
<ValidationObserver v-slot="{ passes }" ref="observer">
<form v-on:submit.prevent="passes(processForm)" novalidate>
//...
</form>
</option>
这一步也与我们使用 Vue 应用所做的相同,但我们在本例中添加了ref="observer"
,因为我们将在步骤 8中需要它。
- 开始用
<ValidationProvider>
组件重构<form>
元素中的所有<input>
元素,如下所示:
// pages/contact.vue
<ValidationProvider name="name" rules="required|min:3" v-slot="{ errors, invalid, validated }">
<label v-bind:class="[invalid && validated ? {'is-invalid-label':
'{_field_}'} : '']">Name
<input
type="text"
name="name"
v-model.trim="name"
v-bind:class="[invalid && validated ? {'is-invalid-input':
'{_field_}'} : '']"
>
<span class="form-error">{{ errors[0] }}</span>
</label>
</ValidationProvider>
这一步也与我们对 Vue 应用所做的相同,但在本例中,我们在v-slot
指令中添加了两个作用域插槽数据属性invalid
和validated
,用于有条件地将类绑定到<label>
和<input>
元素。因此,如果我们对invalid
和validated
都得到true
,那么我们将分别将is-invalid-label
和is-invalid-input
类绑定到元素。
For more information about the Validation Provider's scoped slot data properties, please visit https://vee-validate.logaretm.com/v2/guide/components/validation-provider.html#scoped-slot-data.
- 通过添加以下数据属性与
v-model
输入元素同步,重构<script>
块中的data
函数。我们还将在methods
选项中添加两种方法,如下所示:
// pages/contact.vue
export default {
data () {
return {
name: null,
email: null,
subject: null,
message: null
}
},
methods:{
clear () {
this.name = null
this.email = null
this.subject = null
this.message = null
},
processForm (event) {
alert('Processing!')
console.log('Posting to the server...')
this.clear()
this.$refs.observer.reset()
}
}
}
这一步也与我们在 Vue 应用中所做的相同,但在本例中,我们在processForm
中为methods
选项添加了clear
方法和reset
方法。<ValidationObserver>
组件在提交表单后不会重置表单的状态,因此我们必须手动执行,在步骤 6中将观察者作为参考传递,然后我们可以通过this.$refs
从 Vue 实例访问它。
- 将这三个作用域插槽数据属性
dirty
、invalid
和validated
添加到<ValidationObserver>
组件中,用于切换警报和成功消息,然后按照如下方式重构此组件:
// pages/contact.vue
<ValidationObserver v-slot="{ passes, dirty, invalid, validated }" ref="observer">
<div class="alert callout" v-if="invalid && validated">
<p><i class="fi-alert"></i> There are some errors in your
form.</p>
</div>
//...
<div class="success callout" v-if="submitted && !dirty">
<p><i class="fi-like"></i> Thank you for contacting
me.</p>
</div>
</ValidationObserver>
export default {
data () {
return {
submitted: false
//...
}
},
methods:{
processForm (event) {
console.log('Posting to the server...')
this.submitted = true
//...
}
}
}
在最后一步中,我们添加了一个默认为false
布尔值的submitted
数据属性,当表单以processForm
方法提交时,该属性将被设置为true
。另一方面,当作用域插槽的invalid
和validated
均为true
时,警报消息块可见;当submitted
属性均为true
且dirty
作用域插槽数据属性均为false
时,成功消息块可见。如果其中一个输入字段是“脏的”——换句话说,当输入字段中存在字母时,我们从dirty
属性得到一个true
布尔值。
您可以看到,我们的 Nuxt 应用中的重构代码与我们在 Vue 标准应用中所做的非常相似。但在 Nuxt 应用中,我们为表单添加了更复杂的逻辑,例如切换警报和成功消息,有条件地将类绑定到<label>
和<input>
元素,以及在提交表单时重置<ValidationObserver>
组件。对于其余的输入元素,重构过程是相同的,您可以在本书的 GitHub 存储库/chapter-7/nuxt-universal/sample-website/
中找到。
总结
在本章中,我们介绍了在各种表单输入上使用v-model
进行 Vue 表单验证。您已经学习了基本和动态值绑定,以及如何使用修饰符更改默认输入事件和类型转换。您还学会了使用vee-validate
插件来简化验证。最后,我们设法将这些应用于 Nuxt 应用。
在下一章中,我们将探讨如何在 Nuxt 应用中添加服务器端框架。您将学会使用 Koa 创建一个简单的 API 并将其与 Nuxt 集成,并使用 HTTP 客户机 Axios 来使用 API T0T 请求 API 数据。此外,还将向您介绍一个基于 webpack 的简约构建系统,称为 Backpack,它将简化我们用于单文件组件 Vue 应用的自定义 webpack 配置。您还将学习如何在 Nuxt 应用中使用此构建系统。所以,请继续关注!**
版权属于:月萌API www.moonapi.com,转载请注明出处