模式

介绍

FormKit的模式是一种可序列化为JSON的数据格式,用于存储DOM结构和组件实现,包括FormKit表单。尽管专门用于实现和生成表单,但该格式能够生成任何HTML标记或使用任何第三方组件。

使用FormKit的<FormKitSchema>组件来渲染模式,该组件默认情况下不会全局注册。您需要导入它:

import { FormKitSchema } from '@formkit/vue'

表单生成示例

FormKit提供了对使用模式生成表单的一流支持。这使得可以将生成的表单存储在数据库、文件甚至二维码中!要生成一个表单,将您的模式数组传递给<FormKitSchema>组件的:schema属性。

<FormKitSchema :schema="yourSchemaArray" />

让我们来看一个快速示例:

加载实时示例

我们在上面看到了许多功能,包括$el$cmp属性,$formkit属性的简写形式,验证,条件渲染,标签,帮助文本和多种类型的输入。我们将在本页面的其余部分详细介绍这些功能。

模式数组

模式是一个对象或字符串(称为“模式节点”)的数组,其中每个数组项定义一个单独的模式节点。有3种类型的模式节点:

  1. 文本节点 - 由字符串生成。
  2. HTML元素 - 由$el属性定义。
  3. 组件 - 由$cmp属性定义。
  4. FormKit组件 - 由$formkit属性定义。对完整的$cmp格式的语法糖。

模式支持高级功能,如条件逻辑布尔运算符循环插槽数据作用域 - 所有这些功能都保证序列化为字符串。

HTML元素($el)

使用$el属性定义HTML元素。您可以使用$el来渲染任何HTML元素。可以使用attrs属性添加属性,使用children属性分配内容:

加载实时示例
tip

请注意在上面的示例中,style属性是独特的,它应该被定义为一个样式到值对的对象,而不是一个字符串。

组件($cmp)

组件可以使用$cmp属性定义。$cmp属性应该是一个字符串,引用全局定义的组件或通过library属性传递给FormKitSchema的组件:

加载实时示例
组件作为props

为了通过library属性传递具体的组件,最好使用Vue的markRaw签名包装您的库。

引用

除了模式数组(和可选的库),FormKitSchema对象还可以包括一个data属性。然后可以直接在模式中引用数据对象中的值 - 并且模式将保持原始数据对象的响应性。

要引用数据对象中的值,只需使用美元符号$后跟数据对象的属性名。引用可以在attrsprops、条件和children中使用:

加载实时示例
重要提示

请注意在上面的示例中,我们使用了一个数组来连接“Hello”和“$location”。我们这样做是因为模式中的数据引用和逻辑表达式必须始终以美元符号$开头 - 否则它们将被视为未解析的字符串字面量。

引用函数

模式支持调用您原始引用数据中的函数 - 甚至可以将数据引用作为该函数的参数!

加载实时示例

深层引用

就像JavaScript一样 - 您可以使用点语法object.property访问深层嵌套对象的属性:

加载实时示例
保留字

模式引用可以具有任何结构或属性,但在数据引用对象的根部有两个保留字:$slots$get

表达式

模式还支持布尔逻辑、比较和算术表达式。这些表达式可以在任何可以使用数据引用的地方使用(attrsprops、条件语句和children):

加载实时示例
标记表达式

表达式必须始终以$开头。如果表达式的第一个元素是数据引用(例如:$count + 2),那么它已经以$开头,不需要进一步标记。然而,通常表达式的第一个字符不是美元符号 - 这些表达式需要用$:进行"标记" - 例如$: ($count * 3) - 7

虽然它看起来非常像JavaScript - 模式表达式不是JavaScript。它们更适合被视为模板语言。表达式在setup中被编译为功能性JavaScript,但语法与JavaScript不完全兼容。这提高了性能,并提供了一个关键的安全层,因为只有明确公开的数据和功能才能被执行。

模式表达式仅限于以下运算符和括号:

运算符用例
+加法
-减法
*乘法
/除法
%取模
&&布尔与
||布尔或
===严格相等
!==严格不相等
==宽松相等
!=宽松不相等
>=大于等于
<=小于等于
>大于
<小于

条件语句

FormKit模式可以利用引用和表达式使模式节点和属性具有条件性。这些条件可以通过两种方式添加:

  • $el$cmp节点上的if属性。
  • if/then/else对象

if属性

$el$cmp模式节点都可以利用if属性,它大致相当于Vue中的v-if。如果分配给if属性的表达式为真,节点将被渲染,否则将不会被渲染:

加载实时示例

if/then/else对象

if/then/else对象允许更复杂的条件逻辑。它可以用于有条件地渲染节点、模式节点列表、attrs对象的值或props对象的值。还可以嵌套if/then/else对象以创建更复杂的结构 - 类似于JavaScript中的else if语句。

在模式节点上使用if/then/else

您可以在通常使用模式节点的任何地方使用if/then/else对象。这包括根模式数组或另一个模式节点的children属性:

加载实时示例

在attrs和props上使用if/then/else

您还可以使用if/then/else语句有条件地输出attrsprops的值:

加载实时示例

循环

$el$cmp模式节点都支持循环。循环语法类似于Vue中的v-for,并期望迭代一个对象或数组,并将当前迭代值分配给一个属性。可选地,您还可以捕获当前迭代的索引或属性:

加载实时示例
类型转换

有时模式表达式需要将字符串转换为数字。例如,在迭代过程中,键始终是字符串值,因此在上面的示例中,需要将$key转换为整数后再加上1。要执行此转换,我们只需将其乘以1:$key * 1,然后再执行加法。

插槽

模式可以在模式中的任何位置呈现<FormKitSchema>组件的插槽内容,就像呈现普通模式节点一样。所有作用域插槽都会自动提供给模式,存储在$slots引用对象下:

加载实时示例

绑定attrs和props

有时需要将变量或未知属性或props的对象传递给$cmp$el。在Vue中,我们可以使用v-bind来实现这一点 - 在模式中,我们使用bind属性:

加载实时示例

原始值

有时候需要阻止解析给定的属性或prop。可以通过在属性或prop前加上__raw__来实现:

{
  $cmp: 'PriceComponent',
  props: {
    __raw__price: '$2.99'
  }
}

在上面的示例中,__raw__前缀将被移除,并且未解析的值$2.99将作为price prop传递给PriceComponent

另一个使用场景是渲染FormKit组件。<FormKit>组件有一个sections-schema prop,允许用户传递部分schema与其输入的各个部分合并。在这种特殊情况下,我们希望将schema块作为原始的JavaScript对象传递给<FormKit>组件。为了实现这一点,我们再次使用__raw__前缀来修饰sectionsSchema prop:

加载实时示例

请注意,如果从上面的示例中删除__raw__前缀,前缀将不再起作用 — 这是因为在创建组件时,sectionsSchema prop的值已经被解析而不是作为JavaScript对象传递。

FormKit输入

虽然schema可以用于几乎任何目的,但主要目标是让开发人员使用可序列化的数据格式构建复杂和动态的表单。使用schema与FormKit输入很好地满足了这个用例。

假设你已经全局注册了FormKit组件 —— 你可以通过使用$cmp类型的schema节点从schema中渲染FormKit输入:

加载实时示例

简写

虽然cmp语法是通用的,适用于任何Vue组件,但对于FormKit输入来说有点冗长。为了简化操作,FormKit支持第四种节点类型$formkit,它是完整的$cmp格式的语法糖。

使用$formkit简写时,props对象会与顶级属性($formkit的兄弟节点)进行扁平化处理。例如:

加载实时示例

访问其他输入

schema格式有一个专门针对FormKit输入的内置函数:$get函数。该内置函数允许schema访问任何其他FormKit输入的上下文对象(即使在当前表单之外) —— 前提是所讨论的输入具有明确声明的id prop。这使得schema能够有条件地响应你自己输入的状态:

加载实时示例

表单

要渲染一个表单元素,可以使用$formkit: 'form' schema节点,或者将<FormKitSchema>组件包装在<FormKit type="form">组件中:

加载实时示例