赣州新闻网

首页 / 科技

准备迎接Vue3,使用Vue Composition API生成干净可扩展的表单

2020-04-01 · 赣州新闻网 · 科技


准备迎接Vue3,使用Vue Composition API生成干净可扩展的表单

表单是前端开发中最棘手的部分之一,您可能会在其中发现很多混乱的代码。

Vue.js 2之类的基于组件的框架在提高前端代码的可伸缩性方面做了很多工作,但是f n * ; d / I形式问题仍然存在。

在本教程中,我将向您展示新的Vue Composition API(属: # F ( V d D于Vue 3)将如何使您的表单代码更加整洁和可扩展。

为什么表单代码经常很烂

像Vue这样的( R ~ A Q x Z ( 基于组件的框架的关键设计模式是组件组合。该模式告诉我们将应用程序的特性a 6 d B - 1 f m抽象为独立的、单一用途的组件,这些组件使用属性和事件来进行状态通信。

然而,在这种模式下,表单不能被很好地抽象出来,因为表单的功能和状态并不明显属于任何一个组件,因此将其分离常常会导致与它所解决的问题一样多的问题。

直到Vue 2为止,Vue都不具备在组件之间重用代码的强大方法。这在表单中很重要,因为表单输入通常明显不同,但在功能上有许多相似之处。

Vue 2提供的代码重用的主要方法是mixin,许多人认为这是公然的反模式。

Vue Composition API

Composition API是使用Vue.js定义组件的新方法,它将成为Vue 3的t 6 K _ e b @核心功能。它现在也可以在Vue 2中作为插件使用。

这个新的API旨在解决我提到的一些问题(不仅在形式上,而且在前端应用程序架构的任何方面)。

如果您对Compos7 9 - X P a v 1 itionC e : API还是不熟悉,或者不& J A *清楚它的用途,建议您先阅读文档,以及我写的另一篇文章《何时使用新的Vue Composition API(何时不使用)》。

以及我制作的Vue3 Composition API 备忘单,私信回复:“vue3”获取

准备迎接Vue3,使用Vue Composition API生成干净可扩展的表单

vuY | q e { @ {e3备忘单

Composition API不能替代经` P Y l n _典的Vue API,而是可以在需要7 + , e K q t o时使用的东西。正如您将在本文中看到的那样T Q @ X q - p f,创建干净且可伸缩的表单代码是一个完美的用例。e - ] 4 o


将Composition API添加到Vue 2项目

由于我是在Vue 3发布之前编写本教程的,所以让我们将Composition API作为插件添加到Vue 2项目中。

$ vue create composition-api-form
$ cd composition-api-form
$ npm i -S @vue/composition-api

接下来,让我们将插件添加到main.js中的[ & * { ?Vue实例中。

import Vue from \"vue\";
import App from \"./App.vue\";

import VueCompositionApi from \"@vue/composition-api\";
Vue.use(VueCompositionApi);

new Vue({
render: h =&gP ` 6 V i $t; h(App)
}).$mE e ; iount(\'#app\');

创建表单Input组件

为了使这个例子简单,我们将创建一个仅包含两个输入的表单——名称和电子邮件。让我们将它们创建为自己的独立d Z Z G 8 S p !组件。

$ touch src/componD v & m & Vents/InputName.vue
$ touch src/components/InputEmail.vue

现在让我们以典型的方式设置InputName组件模板,其中包括带有 v-model 指令的HTML输入元素,该模板与该组件创建双向绑定。

src/components/InputName.vue

<template>
<div>
<Y z k zlabel>
Name
<inp4 - m 6 u r ` Dut type=\"text\" v-model=\"input\" name=\"nK $ 9 $ame\" />
</label>
</div&gs t ^t;
</template>
<scripm = X 7 et>
export default {
name: \'InputName\'
}
</script>

设置form

让我们暂时把输入放在一边,然后设置表单。您可以将其作为一个单独的组件来创建,以使其可重用,但是为了本教程的简单性,我将在App组件模板中声明它。

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

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

src/App.vue

<template>
<div id=\"app\">
<fG D / H } m j 5orm novalidate @submit.prevent= D a W f )"o? Y F / ` j 5 I dnSubmit\">
<InputName v-model=\"q R B [ i - ( / ?name\" />
<InputEmail v-model=\"email\" />
&l3 I G [ 7 9 8t;button type=\"submit\">Submit</button>
</form>
</div>
</template&gi R _ ! 1 v $ m !t;
<script>
import InputName from \"n ? w s ! x *@/componenT , 0 }ts/InputName\";
import InputEmail from \"@/componentsi q H */InputEmail\";
export default {
name: \'App\',
components: {
InputName,
InputEmail
}
}
</scri` F | 9 K I U E Bpt>

现在让我们使用Composit- Z } p M t . 1ion API定义表单功能。我们将向组件定义添加一个 setup 方法,在这个方法中,我们将使用Composition API的 ref 方法声明两个状态变量 name 和 email。这个方法需要从Compos~ ; U } 0 = e .ition AT g 9 J S $ J yPI包中导入。

然后,我们将声明一个 onSubmit 函数来处理表单提交。我不会指定任何功能,因o Q # ; 9 8 t default {
name: \"App\",
setup () {
const name = ref(\"\");
const email = ref(\= ! G N 9 5 o"3 * + m T\");g g g H j 0 y
function onSubmit() {
// 提交到后端或任何你喜欢的
console.log(y : ,na6 h ) x 2 B Zme.value, email.valueu c N O & X - {);
}
return {
name,
email,
onSubmit
}
},
...
}

设置Input

接下来D D ^ ! K O h & M,我们将定义 InputName 组件的功能。

由于父表单对这个组件使用的是 v-modelR C 7,重要的是声明了一个prop值,该值将是双向绑定功能实现的一2 F O $ 3 n j X部分(一半)。

让我们创建一个l * Q L 7 r U setup 函数,将props传递到这个方法中,从而使我们能够访问组件实例方法。我们可以解构第二个参数并获得 emit 方法。我们将需要q % ^ a d g x它来完成 v-model 双向绑定的另一半,也就是说,响应地发出input的新值。

在此之前,让我们声明一K 6 { g $ n 0 P K个状态变量 input,它将绑定到我们在模板中声明的input HTML元素。

这个变量的值是我们将要定义的composition function(复合函数) useInputValidato@ V :r 中返回的值。这个函数将处理所有常见的验证逻辑。

我们将把值prop+ ! ~ T传递给这个方法,第二个参数是5 Y n & Y 3 G一个回调函数,它返回经过验证的输入值。让我们使用这个回调来将这个输入作为事件发出,并实现/ q F l v-modJ Z 3 $ j k H n el 契约。

import useInputt n i R %Validator from \"@{ Z _ 9/features/useInputValidator\";

export default {
name: \"InputName\",
props: {
value: String
},
s; X @ ) [ } ^ 6eM t 7 / tup (props, { emit }) {
const { input } = useInputValidator(
props.value,
value => emit(\"input\", value)
);
return {
input
}
}
}

Input验证器功能

现在让我们创建 useInpuB T v 8 ^ l ( atValidator 合成V w a E函数。为此,我们将首先创建一个 features 文件夹,然后为其创建一个模块文件。| q _ O n g g ) g

$ mkdir src/features
$ touch src/features/useInputValidator.js/ 9 G ~ |

在模块文件中,我们导出一个函数,我们刚刚看到它将需要两个参数——从父窗体接收z a @到的 value prop(我们将其称为 startVal)和将被称为 oz . { r . a ) :nValidate 的回调方法。

请记住! 3 ,这个函数需要返回一个 input 状态变量,因此让我们来声明它,分配一个用prop提供的初始值的ref。

在从函数返回 input3 n ! ~ J Y g 7 值之前,让我们看一下它的值,并使用input作为参数调用 onValidate 回调。

srT : w R ` 0 9 J }c/features/useInputValidator.js

import} m C 4 { ref, watch } from \"@vue/composition-api\";

ex. B W % hport defau. % K w ~ * o )lt function (startVal, onValidate) {
let input = ref(startVam ; b _l);
watch(in N P o H ! ; N #put, value => {
onValidate(! k o & G s 5 Dvalue);
});
retu^ 7 o D Z q K E |rn {
input
}A S w # ^ K i j {
}

添加验证器

下一步是添加验证器功能,对于 InputE t - mName 组件,我们只有一个验证规则——minLength,确保输入为三个或更多字符。尚未创建的 InputEmail 组件将需要电子邮件验证。

现在,我们将在src/validateators.js中创建这些验证器。在实际的项目中,您可能会改用第三方库。

不会详细介绍验证器功能,但需要注意以下两点:

  • 这些是返回函数的函数。这种结构允许我 b w们通过传递成为闭包一部分的参数来定制验证。
  • 每个验证器返回的函数总是返回一个字符串(错误消息),如果没有错误,则返回null。

src/validators.js:

const minLength = min => {
return input => input.length < min
? `Value must be at least ${min} characters`
: null;
};

const isE; ; 4 d w者定义它所需要的验证,因此,让我们首先向 validators 中添加另一个参数,该参数应* , ? Q C Z ]该是A & +验证函数的数组。

在input watcher 内部,我们现在将处理验证功能。让我们使用验证器数组的 map 方法,将输入的当前值传递给每个验证器方法。

返回值将被捕获到一个新的状态变量 error 中,我们还将返回到组件使用方。

sr7 I C f S c 0 G @c/fek W b $ = atures/useInputValidator.js:

export default function (startVal, validators, onValid, t G -aA Q = N i mte) {
const input = refv f S # S a(_ L w O t o Y 1 _startVal);
const errw d s a S 8 9 dors = ref();
watch(input, value => {
errors.valua * w ] . z D 3e = validatory c k H / E v xs.map(valik r q . R $ 9 Q dator => validator(value));
onValidate(value);
});
r, L 0 d n jeturn {
input,
errors- - G # % c I -
}
}

最后回到 InputName 组件,我们现在将为 useInputValidator 方法提供所需的三个参数。记住,第二个参数现在是一个验证器数组,所以让我们就地声明w ~ ~ q一个数组,并传入 minLength,我们将从验证器文件中导入该代码。

minLength 是一个工厂函数,因此我们调用传递我们想要指定的最小长度的函数。

现在,我们还从合成函数返回了两个对象——input和error。两者都将从 setup 方法返回,以在组` o .件的渲染上下文中提供可用性。

src/components/I& j A 4 w Y m xnputName.vue

...
i k ymport { minLength } fro^ C Rm \"@/validators\";

export default {
...
setup (proH c G Z p ` O !ps, { emit }2 w z K Z c x q 6) {
consb q 6 B _t { input, errors } = useInputValidator(
props.value,
,
valueB D O ` f . M => emit(\"input\", valu~ U c ~ F , x de)L u c ~ 5 * 4 ~
);
return {
input,
errors
}
}
}

显示0 ; W % @错误

这是我们将添加到此组件的最后S V ^一个功能。不过,在继续之前,请花点时间了解一下此代码比我们使用mixin所看到的代码更具可读性,这一点很# 0 $ ? ` : - ^重要。

一方面,我们清楚地看到了状态变量i ; % l S的声明和修改位置,而无需浏览到单独的mixin模块文件。另一方面,我们不必担心局部变量和组合函数之间的名称冲突。

转到 InputName 组件模板,现在可以显示一系列潜在的` A J错误。让我们将其委托给一个名为 ErrorDisplay 的( / |显示组件。

<temy N ^ z m  @plate>
<div>
<label>
Name
<input type=\R 0 8 w H ? X"text\" v-model=\"input\" name=\"name\" />
</label>
<ErrorDisplay :errors=\"errors\" /&3 2 } t 4 xgt;
</div>
</template>
<script ) u I j w>
...
import Errf ! g $ g P M 0 LorDisplay from \"@/comr } s d X kponents/ErrorDisplay\";

export default* ? q 7 + I: {
...
components: {
ErrorDisplay
}
}
</script>

ErrorDisplay 的功能太简单了,这里就不显示了。

重用代码

这就N + _ 5 k K }是我们基于Composition API 表单的基本功能。本教程的目标是创建干净的、可伸缩的表单代码,我想通过定义我们的第二个自定义输入 InputEmail 向您证明这一点。

如果您达到了本教程的目标,那么在没有我的说明情况下,您可以毫无困难地理解它!

src/components/InputEmail

<template>
<div>
<label>
Email
<input type=\"email\"E # T K N 2 v-m- Z E 2 ; ( rodel=\"input\" name=\"email\" />
</lah U s 5 X 6 wbel>
<Err% , 7 HorDispla1 1 _y v-if=\"input\" :errors=\"errors\" />
</Y a ) r F 9div>
</template~ p = r M J x M ]>
<script>
import useInputValidator from \"@/features6 R k/useIn: f kputVai Z E f ! Nlidator\";
import { isEmail } from \"@/validators\";
import ErrorDisplay! ~ m % ` x J 6 from \"./ErrorDisplayw * O G R 3 z ; .\";

e/ b # x h m u Uxport default {
name: \"InputEmail\",
props: {
value~ e ! t O D w C: String
},
setup (props, { emit }) {
const { input, errors } = useInputValidator(
props.value,
,
value => emit(\"input\", value)
);
return {
input,
errorsM ` L d g 4 D
}
},
compon7 J S c & r p @ 5ents: {
ErrorDisplay
}W O N i 4 ` 1 9 s
}
</script>

完整源代码L r * ( Q * 8 I,请私信回复:“vue3-form”

准备迎接Vue3,使用Vue Composition API生成干净可扩展的表单

本文完全源^ E B w f码


如果对你有所启发和帮助,可以点个关注6 # v n V、收藏,也可以留言讨论,这是对作者的最大鼓励6 t T。

作者简介:Web前端工程师,全栈开发工程师、持续学习者。

现在关注《前端外文精选》公众号,送精品视频视频教程大礼包!

#Vue.js#

确保项目视频工作工厂文章设置告诉石城