FormKit 使用了一个独特的分层配置系统,非常适合表单。要理解这种配置是如何工作的,我们需要回答4个问题:
每个 <FormKit>
组件都有自己的核心节点实例。这个节点负责组件的几乎所有功能。有3种类型的核心节点:输入,列表和组(表单只是一种类型的组!)。
没有全局的 FormKit 实例来控制应用程序。相反,你可以把每个节点看作是它自己的小应用程序 - 完整的配置。
关于节点的最后一点 - 它们都可以有父节点。组和列表也可以有子节点。例如,一个登录表单可能有两个子节点 - 邮箱和密码输入。你可以把这种关系画成一个简单的树状图:
在创建我们称之为核心节点的这些"迷你应用程序"时,可以传入一些选项。除非在极其高级的使用场景中,你不会创建自己的核心节点 - 这通常是由 <FormKit>
组件为你完成的。然而,全局定义一些节点选项可能会很有用。这是通过 @formkit/vue
插件完成的 - 💡 核心节点选项与 @formkit/vue
插件选项相同。
例如,在典型的 FormKit Vue 注册中,我们使用 defaultConfig
,这只是一个返回核心节点选项的函数:
import { createApp } from 'vue'
import App from 'App.vue'
import { plugin, defaultConfig } from '@formkit/vue'
// 👀 defaultConfig 只是一个返回核心节点选项的函数!
createApp(App).use(plugin, defaultConfig)
以下是在注册 FormKit 或单独创建节点时可以使用的所有可用选项的列表。传递给 @formkit/vue
插件的选项将在创建每个 <FormKit>
组件的核心节点时应用。
createNode({
/**
* 用于重命名全局 "FormKit" 组件。
*/
alias: 'FormKit',
/**
* 这个数组通常由 FormKit 组件为你构建。
*/
children: [],
/**
* 配置设置的对象。继续阅读以了解更多。
*/
config: {},
/**
* 节点的名称 - 通常这是映射到你的输入的名称。
*/
name: 'inputName',
/**
* 父节点 - 这通常由 FormKit 组件为你设置。
*/
parent: null,
/**
* 插件函数的数组
*/
plugins: [],
/**
* 默认属性值,继续阅读以了解更多。
*/
props: {},
/**
* 用于重命名全局 "FormKitSchema" 组件。
*/
schemaAlias: 'FormKitSchema',
/**
* 所有的只有3个值之一:'input','group',或 'list'
*/
type: 'input',
/**
* 节点的初始值。
*/
value: 'foobar',
})
defaultConfig
?熟悉FormKit的开发者会注意到,上面列出的节点选项与可以传递给 defaultConfig
函数的值略有不同。
FormKit的许多功能,如验证、输入和Vue支持,都是由第一方插件提供的。defaultConfig
函数在将这些插件交给Vue插件作为节点选项之前,会对许多这些插件进行配置。因此,defaultConfig
可以接受任何上述节点选项,但也可以接受一些额外的选项:
defaultConfig({
/**
* 添加或覆盖的验证规则。
* 参见验证文档。
*/
rules: {},
/**
* 注册的语言环境。
* 参见国际化文档。
*/
locales: {},
/**
* 添加或覆盖的输入定义。
* 参见自定义输入文档。
*/
inputs: {},
/**
* 覆盖的明确的语言环境消息。
* 参见国际化文档。
*/
messages: {},
/**
* 当前活动的语言环境。这实际上是一个配置设置,但
* defaultConfig将其作为顶级值接受,以改善DX。
*/
locale: 'en',
/**
* 接受任何上述节点选项。
*/
...nodeOptions,
})
所有核心节点都有一个 props
对象(node.props
)。FormKit核心和任何第三方插件或代码都可以读取和写入此对象的值。事实上,FormKit的几乎每个功能都引用 node.props
来确定它应如何操作。
例如,验证插件查看 node.props.validation
来确定是否有任何规则需要运行。所以真正的问题是 —— 这些属性是如何设置的?设置属性有3种主要机制:
让我们看看我们可以如何通过这三种方式设置输入的验证规则(node.props.validation
):
如果你有一个节点实例,你可以直接给它分配一个属性值:
传递给 <FormKit>
输入的任何属性都会分配给 node.props
对象(你知道的)。
在注册 @formkit/vue
插件(或使用 @formkit/nuxt
和 formkit.config.ts
)时,你可以提供属性值,以便注入到所有 <FormKit>
组件中。
类似于全局选项,<FormKitProvider>
组件允许你指定应注入其子组件的"全局"配置选项。这种技术可以用来为应用的特定部分创建一个"范围内"的配置,覆盖应用的特定部分的全局选项,或者为 FormKit 库提供更有针对性的加载。
使用 <FormKitProvider>
组件时,所有全局定义的选项(来自全局插件)都会被移除,只有提供者提供的选项会在其范围内的任何 <FormKit>
组件上使用。
启用 autoImport: true
的 @formkit/nuxt
模块会自动将使用 FormKit 的组件包装在一个 <FormKitProvider>
组件中。这样可以防止 formkit 被包含在你的入口包中。
Props 非常强大,但除了 node.props
,核心节点都有一个配置对象 node.config
。这就是配置层次结构的作用。node.config
对象就像 node.props
的初始值。如果请求一个给定的 prop,比如 node.props.validation
,并且该属性没有使用上述任何方法明确设置,那么 FormKit 将检查 node.config
对象是否有值。如果它没有值,那么它会递归检查节点父对象的配置对象——然后是祖父对象的配置对象——依此类推——直到找到一个值或者到达没有父对象的节点。
这在实践中意味着什么?当你将表单的树状结构(及其对应的核心节点)和这种层次配置结合起来时,你可以做一些非常激动人心的事情。例如,我们在这里设置了整个表单的验证可见性:
值得注意的是,插件有自己的继承模型,它与 config
和 props
不同,并在核心文档中有更详细的描述。