将自定义验证应用于 Nuxt 应用程序
让我们将自定义验证应用到示例网站已有的联系页面中。您可能已经注意到现有的联系表单已经使用了 Foundation
(Zurb)的验证功能。使用 Foundation
的表单验证是增强 HTML
表单验证的另一种好方法。
如果您想了解更多关于 |
但如果我们想使用刚刚在 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
配置中添加插件路径:// nuxt.config.js plugins: [ '~/plugins/vee-validate' ]
-
在
build
选项中添加例外:// nuxt.config.js build: { transpile: [ "vee-validate/dist/rules" ], extend(config, ctx) {} }
在
Nuxt
中,默认情况下/node_modules/
文件夹会被排除在转译之外,因此在使用vee-validate
时你会遇到Unexpected token export
的错误。所以,在运行Nuxt
应用之前,我们必须添加/vee-validate/dist/rules.js
以进行转译。 -
就像我们在
Vue
应用中做的那样,导入ValidationObserver
和ValidationProvider
组件:// pages/contact.vue import { ValidationObserver, ValidationProvider } from 'vee-validate' export default { components: { ValidationObserver, ValidationProvider } }
-
从
<form>
元素中移除Foundation
的data-abide
属性,但是用<ValidationObserver>
组件包裹它,并将submit
事件与passes
和processForm
方法绑定到<form>
元素,如下所示:<template> <ValidationObserver v-slot="{ passes }" ref="observer"> <form v-on:submit.prevent="passes(processForm)" novalidate> <!-- 表单内容 --> </form> </ValidationObserver> </template>
这一步也和我们在
Vue
应用中做的相同,但是在这个例子中我们添加了ref="observer"
,因为我们将在第 8 步中需要它。 -
开始使用
<ValidationProvider>
组件重构<form>
元素内部的所有<input>
元素,如下所示:// pages/contact.vue <template> <ValidationProvider name="name" rules="required|min:3" v-slot="{ errors, invalid, validated }" > <label :class="[invalid && validated ? {'is-invalid-label': '{_field_}'} : '']"> 姓名 <input type="text" name="name" v-model.trim="name" :class="[invalid && validated ? {'is-invalid-input': '{_field_}'} : '']" > <span class="form-error">{{ errors[0] }}</span> </label> </ValidationProvider> </template>
这一步也和我们在
Vue
应用中做的相同,但是在这个例子中,我们在v-slot
指令中添加了两个作用域插槽数据属性:invalid
和validated
,用于有条件地将类绑定到<label>
和<input>
元素。因此,如果invalid
和validated
都为true
,那么我们将分别把is-invalid-label
和is-invalid-input
类绑定到这两个元素上。有关
Validation Provider
的作用域插槽数据属性的更多信息,请访问 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('处理中!') console.log('提交到服务器...') this.clear() this.$refs.observer.reset() } } }
这一步也和我们在
Vue
应用中做的相同,但是在这个例子中,我们在methods
选项的processForm
中添加了clear
方法和reset
方法。<ValidationObserver>
组件在提交后不会重置表单的状态,所以我们必须手动进行重置,方法是在第 6 步中将observer
作为引用传递,然后我们可以通过this.$refs
从Vue
实例访问它。 -
将
dirty
、invalid
和validated
这三个作用域插槽数据属性添加到<ValidationObserver>
组件中,用于切换警告和成功消息的显示,然后让我们按如下方式重构这个组件:// pages/contact.vue <template> <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> </template> <script> export default { data() { return { submitted: false //... } }, methods: { processForm(event) { console.log('Posting to the server...') this.submitted = true //... } } } </script>
在最后一步中,我们添加了一个默认值为
false
的submitted
数据属性,当表单通过processForm
方法提交时,该属性将被设置为true
。另一方面,当作用域插槽中的invalid
和validated
同时为true
时,警告消息块将显示;而当submitted
属性为true
且作用域插槽的dirty
属性为false
时,成功消息块将显示。如果任一输入字段是"dirty"
的(换句话说,当输入字段中存在字符时),dirty
属性将返回true
布尔值。
您可以看到,我们在 Nuxt
应用中重构的代码与标准 Vue
应用中的做法非常相似。但在 Nuxt
应用中,我们为表单添加了更复杂的逻辑,例如切换警告和成功消息、有条件地将类绑定到 <label>
和 <input>
元素,以及在表单提交时重置 <ValidationObserver>
组件。其余输入元素的重构过程与此相同,您可以在本书的 GitHub
仓库 /chapter-7/nuxt-universal/sample-website/
中找到相关代码。