使用Vue Composition API写出清晰、可扩展的表单实现(2)

将添加 novalidate 属性,让浏览器知道我们将提供自定义验证。还将监听表单的 submit 事件,防止表单自动提交,并使用声明的 onSubmit 方法处理该事件。

然后,添加 InputName 和 InputEmail 组件,并分别将本地状态值 name 和 email 进行绑定。

src/App.vue

<template> <div> <form novalidate @submit.prevent="onSubmit"> <InputName v-model="name" /> <InputEmail v-model="email" /> <button type="submit">Submit</button> </form> </div> </template> <script> import InputName from "@/components/InputName"; import InputEmail from "@/components/InputEmail"; export default { name: 'App', components: { InputName, InputEmail } } </script>

接下来使用 Composition API 定义表单功能。在组件定义中添加 setup 方法,并使用 Composition API 提供的 ref 方法声明两个状态变量 name 和 email。

然后声明一个 onSubmit 函数来处理表单提交。

src/App.vue

// 其余省略 ... import { ref } from "@vue/composition-api"; export default { name: "App", setup () { const name = ref(""); const email = ref(""); function onSubmit() { // 这里可以写提交后端的逻辑 console.log(name.value, email.value); } return { name, email, onSubmit } }, ... }

设置输入组件

接下来,将定义 InputName 组件的功能。

在组件上使用了 v-model 指令,就和组件创建了双向绑定,在组件内部的 props 上定义 value 来接收值,这只做了一半的工作。

创建一个 setup 函数。props 和组件实例被传递到这个方法中,使我们能够访问组件实例上的方法。

用解构的方式在第二个参数中获得 emit 方法。将需要它来完成 v-model 的双向绑定的另一半工作,即触发 input 事件,修改绑定的值。

在此之前,声明一个状态变量 input,将绑定到我们在模板中声明的 HTML 元素上。

该变量的值是待定义的合成函数 useInputValidator 执行后返回的值。此函数将处理所有常见的验证逻辑。

把 prop.value 传递给这个方法作为第一个参数,第二个参数是一个回调函数,接收经过验证后的输入值,在这个回调函数中触发 input 事件,修改 v-model 绑定的值,实现和父组件双向绑定的功能。

src/components/InputName.vue

<template> <div> <label> Name <input type="text" v-model="input" /> </label> </div> </template> <script> import useInputValidator from "@/features/useInputValidator"; export default { name: "InputName", props: { value: String }, setup (props, { emit }) { const { input } = useInputValidator( props.value, value => emit("input", value) ); // 绑定在元素上 return { input } } } </script>

输入框验证功能

开始创建 useInputValidator 组合函数,为此,首先创建一个 features 文件夹,然后为其创建一个模块文件。

$ mkdir src/features $ touch src/features/useInputValidator.js

在模块文件中,将导出一个函数,它需要两个参数: 从父表单接收到的值,用 startVal 接收;以及一个回调函数,用 onValidate 接收。

函数需要返回一个 input 状态变量,因此需要声明它,通过调用 ref 并提供 startVal 的值进行初始化。

在从函数返回 input 之前,观察该值的变化,并调用 onValidate回调,传入最新的 input 的值。

src/features/useInputValidator.js

import { ref, watch } from "@vue/composition-api"; export default function (startVal, onValidate) { let input = ref(startVal); watch(input, value => { onValidate(value); }); return { input } }

添加验证器

下一步添加验证器函数。对于 InputName 组件,只有一个验证规则 minLength,确保输入是三个字符或更多。尚未创建的 InputEmail 组件将需要电子邮件验证规则。

将在 src 文件夹中创建模块 validators.js,并写这些验证器。在实际的项目中,您可能会使用第三方库。

不会详细介绍 validator 函数,但是有两件重要的事情需要注意:

这些是返回函数的函数。这样的结构允许我们通过传递成为闭包一部分的参数来定制验证规则。

每个验证器返回的函数总是返回一个字符串(错误消息),如果没有错误,则返回 null。

src/validators.js

const minLength = min => { return input => input.length < min ? `Value must be at least ${min} characters` : null; }; const isEmail = () => { const re = /\S+@\S+\.\S+/; return input => re.test(input) ? null : "Must be a valid email address"; } export { minLength, isEmail };

回到上面的组合函数所在文件 useInputValidator.js 中,我们希望使用需要的验证,给函数添加另一个参数,它是一组验证函数。

在 input 监视器内部,使用数组的 map 方法调用验证函数,将 input 的当前值传递给每个验证器方法。

返回值将在一个新的状态变量 errors 中捕获,也将返回给所在组件使用。

src/features/useInputValidator.js

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/88e0513d2b183ccefe64e12f5c9a81b0.html