FormKit包含了许多输入,但您也可以定义自己的输入,自动继承FormKit的增值功能,如验证、错误消息、数据建模、分组、标签、帮助文本等。
如果您的用例需要修改现有输入,比如移动部分、更改或重组HTML元素等,请考虑使用FormKit的输入导出功能。
输入由两个基本部分组成:
如果您刚开始使用自定义输入,请阅读“创建自定义输入”指南。本页面的内容旨在解释自定义输入的复杂性,适用于高级用例,如编写插件或库,并不适用于许多常见用例。
新的输入需要一个输入定义。输入定义可以通过以下三种方式注册到FormKit:
输入定义是包含初始化输入所需信息的对象,例如要接受的props、要渲染的schema或组件以及是否包含任何其他功能函数。定义对象的形状如下:
{
// 节点类型:input、group或list。
type: 'input',
// 要渲染的模式(模式对象或返回对象的函数)
schema: [],
// 要渲染的Vue组件(使用模式 _OR_ 组件,但不能同时使用)
component: YourComponent,
// (可选)<FormKit>组件应接受的特定于输入的props。
// 应为驼峰式字符串的数组
props: ['fooBar'],
// (可选)接收节点的函数数组。
features: []
}
type
属性让我们创建最简单的输入 - 只输出“Hello world”。
即使这个简单的示例不包含任何输入/输出机制,它仍然可以作为完整的输入。它可以有一个值,运行验证规则(它们不会被显示,但可以阻止表单提交),并执行插件。从根本上说,所有输入都是核心节点,输入的定义提供了与该节点交互的机制。
要通过“type”字符串在应用程序的任何地方使用自定义输入(例如:<FormKit type="foobar" />
),可以在defaultConfig
选项中添加一个inputs
属性。inputs
对象的属性名称成为应用程序中<FormKit>
组件可用的“type”字符串。
import { createApp } from 'vue'
import App from 'App.vue'
import { plugin, defaultConfig } from '@formkit/vue'
const helloWorld = {
type: 'input',
schema: ['Hello world'],
}
createApp(App)
.use(
plugin,
defaultConfig({
inputs: {
// 属性将成为<FormKit type="hello">中的“type”
hello: helloWorld,
},
})
)
.mount('#app')
现在,我们已经定义了我们的输入,可以在应用程序的任何地方使用它:
上面的示例通过defaultConfig
扩展了@formkit/inputs
库。然而,FormKit的一个强大功能是它能够从多个插件中加载输入库。这些输入可以在任何可以定义插件的地方进行注册:
让我们重构我们的hello world输入,使用自己的插件:
请注意,在上面的示例中,我们的插件是在实际使用它的元素的父级上定义的!这要归功于FormKit插件的插件继承 - 这是FormKit插件的一个核心功能。
您的输入可以使用 FormKit 的模式 或通用的 Vue 组件来编写。每种方法都有其优缺点:
代码 | 优点 | 缺点 |
---|---|---|
Vue |
|
|
模式 |
|
|
即使您更喜欢使用标准的 Vue 组件编写自定义输入,您仍然可以在输入定义中使用模式。请阅读使用 createInput
扩展基本模式部分。
主要的要点是,如果您计划在多个项目中使用自定义输入,则考虑使用基于模式的方法。如果您的自定义输入仅在单个项目中使用且灵活性不是问题,则使用 Vue 组件。
将来,FormKit 可能会扩展以支持其他框架(例如 React 或 Svelte)。如果您对此感兴趣,请告诉我们!。使用模式编写输入意味着您的输入也将与这些框架兼容(可能需要进行最小更改)。
FormKit 的所有核心输入都是使用模式编写的,以实现最大的灵活性。在编写自己的模式输入时,您有两个主要选项:
重要的是要了解“标准” FormKit 输入的基本结构,它被分解为部分:
上图中的 input
部分通常是您在创建自己的输入时要替换的部分,但保持包装器、标签、帮助文本和消息不变。但是,如果您还想控制这些方面,您也可以从头开始编写自己的输入。
createInput
扩展基本模式要使用基本模式创建输入,您可以使用 @formkit/vue
包中的 createInput()
实用程序。此函数接受 2 个参数:
input
部分(参见上图)。该函数返回一个可直接使用的输入定义。
当将 组件 作为第一个参数提供时,createInput
将生成一个引用您组件的模式对象,并将一个 context
属性传递给您的组件:
{
$cmp: 'YourComponent',
props: {
context: '$node.context'
}
}
当提供模式对象时,您的模式将直接注入到基本模式对象中。请注意,我们的示例现在支持输出“标准” FormKit 功能,如标签、帮助文本和验证:
完全从头开始编写输入,而不使用任何基本模式功能可能是有意义的。在这种情况下,只需提供input定义您的完整模式对象。
在上面的示例中,我们能够重新创建与createInput
示例相同的功能,即标签、帮助文本和验证消息输出。然而,我们仍然缺少许多“标准”的FormKit功能,如插槽支持。如果您尝试发布您的输入或保持与其他FormKit输入的API兼容性,请查看input清单。
对于大多数用户来说,将Vue组件传递给createInput
提供了定制和增值功能之间的良好平衡。如果您完全想要退出基于模式的输入,您可以直接将组件传递给输入定义。
组件输入接收一个单一的属性 - 上下文对象。然后,您可以编写一个组件来包含FormKit所需的功能(标签、帮助文本、消息显示等)。请查看input清单以获取您想要输出的内容列表。
输入有两个关键角色:
您可以从任何用户交互中接收输入,并且输入可以将其值设置为任何类型的数据。输入不仅限于字符串和数字 - 它们可以愉快地存储数组、对象或自定义数据结构。
从根本上说,输入只需要使用一个值调用node.input(value)
。node.input()
方法会自动进行防抖处理,因此可以随意频繁调用它 - 比如每次按键。通常,这看起来像是绑定到input
事件。
context
对象包括用于基本输入类型的输入处理程序:context.handlers.DOMInput
。这可以用于文本类输入,其中输入的值在event.target.value
中可用。如果您需要更复杂的事件处理程序,可以使用“功能”来公开它。
任何用户交互都可以视为输入事件。对于许多原生HTML输入,该交互是通过input事件捕获的。
// 在模式中编写的HTML文本输入:
{
$el: 'input',
attrs: {
onInput: '$handlers.DOMInput'
}
}
在Vue模板中的等效写法:
<template>
<input @input="context.DOMInput" />
</template>
输入还负责显示当前值。通常,您会希望在模式中使用node._value
或$_value
来显示值。这是“实时”的非防抖值。当前已提交的值是node.value
($value
)。在这里阅读更多关于“值结算”的内容。
// 在模式中编写的HTML文本输入:
{
$el: 'input',
attrs: {
onInput: '$handlers.DOMInput',
value: '$_value'
}
}
在Vue模板中的等效写法:
<template>
<input :value="context._value" @input="context.handlers.DOMInput" />
</template>
只有在输入本身上显示值时才应使用未提交的输入_value
- 在所有其他位置,重要的是使用已提交的value
。
您可以在模式中直接引用表达式(例如:$label
)来使用根据<FormKit>
组件传递的标准FormKit属性(如label
或type
)。任何传递给<FormKit>
组件的不是节点属性的属性最终都会出现在context.attrs
对象中(在模式中只是$attrs
)。
如果您需要其他属性,可以在输入定义中声明它们。属性也可以用于内部输入状态(类似于Vue 3组件中的ref
)。FormKit将props
命名空间用于这两个目的(有关此示例的自动完成示例,请参见下文)。属性应始终以驼峰命名法定义,并在Vue模板中使用短横线命名法。
通过使用createInput
助手来扩展基本模式时,传递第二个参数与输入定义值进行合并:
功能是向自定义输入类型添加功能的首选方法。 "功能"只是一个接收核心节点作为参数的函数。实际上,它们是没有继承的插件(因此它们只适用于当前节点)。您可以使用功能来添加输入处理程序,操作值,与属性交互,监听事件等等。
功能在数组中定义,以鼓励尽可能地重用代码。例如,我们在select
,checkbox
和radio
输入上使用了一个名为“options”的功能。
例如,假设您想构建一个输入,允许用户输入两个数字,而输入的值是这两个数字的和:
以下是一些自定义输入的示例。它们不打算全面或用于生产环境,而是用于说明一些自定义输入功能。
这是最简单的输入,不利用FormKit的内置DOM结构,只输出一个文本输入 - 但它是所嵌套组中的一个完全功能的成员,能够读取和写入值。
在上面的示例中,$handlers.DOMInput
是一个内置的方便函数,用于(event) => node.input(event.target.value)
。
让我们看一个稍微复杂一些的例子,它利用createInput
提供所有标准的FormKit结构,同时提供自定义的输入界面。
FormKit为即使是最普通的输入提供了数十个增值功能。在为特定项目编写自定义输入时,您只需要实现实际在该项目上使用的功能。但是,如果您计划将您的输入分发给其他人,则需要确保这些功能可用。例如,标准的<FormKit type="text">
输入使用以下模式作为其input
元素的模式:
{
$el: 'input',
bind: '$attrs',
attrs: {
type: '$type',
disabled: '$disabled',
class: '$classes.input',
name: '$node.name',
onInput: '$handlers.DOMInput',
onBlur: '$handlers.blur',
value: '$_value',
id: '$id',
}
]
上述模式中有几个功能可能不是立即明显的,比如onBlur
处理程序。以下清单旨在帮助输入作者涵盖所有方面:
label
prop must be displayed and linked for accessibility with the for
attribute.label
slot.label
section key.help
prop must be displayed.help
slot.help
section key.context.messages
object must displayed if it is set to visible
.messages
slot.messages
section key.message
slot.message
section key..input
slot.id
attribute (context.id
).name
attribute (context.node.name
).context.handlers.blur
when blurred.node.input(value)
when the user provides input. You can use context.handlers.DOMInput
for text-like inputs.context._value
.disabled
attribute when context.disabled
is true
.bind: '$attrs'
in schemas.