5 分钟教你用阿里 Formily.js 快速做复杂表单

1. Formily 是什么?

Formily 是 alibaba 开源表单框架,抽象了表单领域模型的 MVVM 表单解决方案。

这里引用官网的介绍:

众所周知,表单场景一直都是前端中后台领域最复杂的场景,它的复杂度主要在哪里呢?

  • 字段数量多,如何让性能不随字段数量增加而变差?
  • 字段关联逻辑复杂,如何更简单的实现复杂的联动逻辑?字段与字段关联时,如何保证不影响表单性能?
  • 表单数据管理复杂
  • 表单状态管理复杂
  • 表单的场景化复用
  • 动态渲染诉求很强烈

image.png

这张图主要将 Formily 分为了内核层,UI 桥接层,扩展组件层,和配置应用层。

内核层是 UI 无关的,它保证了用户管理的逻辑和状态是不耦合任何一个框架,这样有几个好处:

  • 逻辑与 UI 框架解耦,未来做框架级别的迁移,业务代码无需大范围重构
  • 学习成本统一,如果用户使用了 @formily/react,以后业务迁移 @formily/vue,用户不需要重新学习

JSON Schema 独立存在,给 UI 桥接层消费,保证了协议驱动在不同 UI 框架下的绝对一致性,不需要重复实现协议解析逻辑。

扩展组件层,提供一系列表单场景化组件,保证用户开箱即用。无需花大量时间做二次开发。

2. 核心优势

  • 高性能
  • 开箱即用
  • 联动逻辑实现高效
  • 跨端能力,逻辑可跨框架,跨终端复用
  • 动态渲染能力

3. formily 能解决什么问题

  • 解决复杂场景,表单性能问题
  • 可以实现复杂的表单联动逻辑
  • 表单状态管理
  • 表单场景化复用
  • 后端也能搭建前端表单

4. 如何用 Formily 渲染一个登录表单

这里有一个场景,我们要实现如下效果:

image.png

正常来说需要用 Antd 等 UI 库写 Form 组件来实现,但是这里我们用 Formily 框架提供的能力来实现,接下来我们先了解一下 Formily 的渲染模式。

4.1 Formily 的渲染模式

Formily 支持 3 种渲染模式,JSX,Markup Schema 和 JSON Schema。我这里主要介绍后两种。

4.1.1 Markup Schema

Markup Schema 的使用方式,如下方代码所示,每个描述标签都代表一个 Schema 节点,与 JSON-Schema 等价,最终也会被编译为 JSON Schema。

<Form
  form={normalForm}
  layout="vertical"
  size="large"
  onAutoSubmit={console.log}
>
  <SchemaField>
    <SchemaField.String
      name="username"
      title="Username"
      required
      x-decorator="FormItem"
      x-component="Input"
      x-validator={{
        required: true,
      }}
      x-component-props={{
        prefix: "{{icon('UserOutlined')}}",
      }}
    />
    <SchemaField.String
      name="password"
      title="Password"
      required
      x-decorator="FormItem"
      x-component="Password"
      x-component-props={{
        prefix: "{{icon('LockOutlined')}}",
      }}
    />
  </SchemaField>

Markup schema 是一个对源码开发比较友好的 Schema 开发模式,同样是使用 SchemaField 组件。

因为用 JSON Schema 在 JSX 环境下很难得到最好的智能提示体验,而且也不方便维护,用标签的形式可维护性会更好,智能提示也很强。

4.1.2 JSON schema

Formily 提供了一套 DSL,可以通过 JSON 渲染表单结构。

下面是一个最简的 formily 定义的 JSON schema,以下 JSON 便可描述 form 的结构。

const normalSchema = {
  type: 'object',



  properties: {



    username: {
      type: 'array',
      title: 'Username',
      required: true,
      'x-decorator': 'FormItem',
      'x-component': 'Input',
      'x-component-props': {
        prefix: "{{icon('UserOutlined')}}",
      },
    },

    password: {
      type: 'string',
      title: 'Password',
      required: true,
      'x-decorator': 'FormItem',
      'x-component': 'Password',
      'x-component-props': {
        prefix: "{{icon('LockOutlined')}}",
      },
    },
  },
};

4.2 如何渲染 JSON Schema?

Formily 提供了 @formily/core@formily/react 包,供我们以 JSON Schema 的形式渲染表单。

另外 Formily 也提供了自定义表单组件的能力。

import React from 'react';
import { createForm } from '@formily/core';
import { Form, FormItem, Input, Password, Submit } from '@formily/antd';
import { createSchemaField } from '@formily/react';
import * as ICONS from '@ant-design/icons';

const normalForm = createForm({
  validateFirst: true,
});

const SchemaField = createSchemaField({
  components: {
    FormItem,
    Input,
    Password,
  },
  scope: {
    icon(name) {
      return React.createElement(ICONS[name]);
    },
  },
});

// render it
const Basic = () => {
  return (
    <Form
      form={normalForm}
      layout="vertical"
      size="large"
      onAutoSubmit={console.log}
    >
      <SchemaField schema={normalSchema} />
      <Submit block size="large">
        Login
      </Submit>
    </Form>
  )
}

优势:

  • 后端也可以通过接口下发 JSON schema 来渲染前端表单,对于一个不了解前端技术的后端同学,也能够写表单。
  • 同构的架构可以保证表单字段与服务端定义的一致,降低了前后端对齐接口协议的成本。

5. Formily Schema

属性 描述 类型 字段模型映射
type 类型 SchemaTypes GeneralField
title 标题 React.ReactNode title
description 描述 React.ReactNode description
default 默认值 Any initialValue
readOnly 是否只读 Boolean readOnly
writeOnly 是否只写 Boolean editable
enum 枚举 SchemaEnum dataSource
const 校验字段值是否与 const 的值相等 Any validator
multipleOf 校验字段值是否可被 multipleOf 的值整除 Number validator
maximum 校验最大值(大于) Number validator
exclusiveMaximum 校验最大值(大于等于 Number validator
minimum 校验最小值(小于) Number validator
exclusiveMinimum 最小值(小于等于) Number validator
maxLength 校验最大长度 Number validator
minLength 校验最小长度 Number validator
pattern 正则校验规则 RegExpString validator
maxItems 最大条目数 Number validator
minItems 最小条目数 Number validator
uniqueItems 是否校验重复 Boolean validator
maxProperties 最大属性数量 Number validator
minProperties 最小属性数量 Number validator
required 必填 Boolean validator
format 正则校验格式 ValidatorFormats validator
properties 属性描述 SchemaProperties
items 数组描述 SchemaItems
additionalItems 额外数组元素描述 Schema
patternProperties 动态匹配对象的某个属性的 Schema SchemaProperties
additionalProperties 匹配对象额外属性的 Schema Schema
x-index UI 展示顺序 Number
x-pattern UI 交互模式 FieldPatternTypes pattern
x-display UI 展示 FieldDisplayTypes display
x-validator 字段校验器 FieldValidator validator
x-decorator 字段 UI 包装器组件 String | React.FC decorator
x-decorator-props 字段 UI 包装器组件属性 Any decorator
x-component 字段 UI 组件 String | React.FC component
x-component-props 字段 UI 组件属性 Any component
x-reactions 字段联动协议 SchemaReactions reactions
x-content 字段内容,用来传入某个组件的子节点 React.ReactNode content
x-visible 字段显示隐藏 Boolean visible
x-hidden 字段 UI 隐藏(保留数据) Boolean hidden
x-disabled 字段禁用 Boolean disabled
x-editable 字段可编辑 Boolean editable
x-read-only 字段只读 Boolean readOnly
x-read-pretty 字段阅读态 Boolean readPretty
definitions Schema 预定义 SchemaProperties
$ref 从 Schema 预定义中读取 Schema 并合并至当前 Schema String
x-data 扩展属性 Object data
x-compile-omitted 忽略编译表达式的属性列表 string[] []

更多细节,可以参考 Formily API 文档

6. 表单联动展示

登录场景我们实现的是一个比较简单的 JSON Schema,仅仅描述了 2 个表单项。

现在有一个新的场景:

我们想实现当 showInput 为 show 时,展示 Input 表单项,hide 时,隐藏 Input 表单项,如下图所示:

image.png

image.png

这是一个一对一联动的 case。

在 Formily 中,联动分为主动联动和被动联动:

  • 主动联动:只需要关注某个字段所依赖的字段即可,依赖字段变化了,被依赖的字段即可自动联动

  • 被动联动:必须要监听一个或多个字段的事件变化去控制另一个或者多个字段的状态

6.1 主动联动

const schema = {


  type: 'object',



  properties: {



    showInput: {

      type: 'string',

      title: 'showInput',

      enum: [

        { label: 'show', value: 'visible' },

        { label: 'hide', value: 'none' },

      ],

      default: 'visible',

      'x-decorator': 'FormItem',


      'x-component': 'Select',

      'x-reactions': {
        target: 'input',
        fulfill: {
          state: {
            display: '{{$self.value}}',
          },
        },
      },
    },
    input: {
      type: 'string',
      title: 'Input',
      required: true,
      'x-decorator': 'FormItem',

      'x-component': 'Input',
    },

  },

};

6.2 被动联动

被动联动怎么写呢,这里举一个例子,实际上只有 x-reactions 参数的区别。在被动联动的表单项中,定义 dependencies 为依赖项:

const schema = {


  type: 'object',



  properties: {



    showInput: {

      type: 'string',

      title: 'showInput',

      enum: [

        { label: 'show', value: 'visible' },

        { label: 'hide', value: 'none' },

      ],

      default: 'visible',

      'x-decorator': 'FormItem',


      'x-component': 'Select',

    },
    input: {
      type: 'string',
      title: 'Input',
      required: true,
      'x-decorator': 'FormItem',
      'x-component': 'Input',
      'x-reactions': {
        dependencies: ['showInput'],
        fulfill: {
          state: {
            display: '{{$deps[0]}}',
          },
        },
      },
    },

  },

};

一对多联动也是类似的,只是增加了一个表单项的区别。

另外,Formily 也支持链式联动,异步联动等联动方式。

7. 表单联动校验

如果我们想实现表单联动校验,要怎么做呢?

例如下图,我们想实现 AA 必须比 BB 大。

image.png

formily Schema 支持写 function 形式的 x-reactions,在参数中我们可以拿到当前 form 实例挂载的其他字段的值,在函数中可以直接做判断。

const schema = {


  type: 'object',



  properties: {



    aa: {
      title: 'AA',
      required: true,
      'x-reactions': `{{(field) => {
          field.selfErrors =
            field.query('bb').value() >= field.value ? 'AA must be greater than BB' : ''
      }}}`,
      'x-component': 'NumberPicker',
      'x-decorator': 'FormItem',


    },

    bb: {
      title: 'BB',
      required: true,
      'x-reactions': {
        dependencies: ['aa'],
        fulfill: {
          state: {
            selfErrors:
              "{{$deps[0] <= $self.value ? 'AA must be greater than BB' : ''}}",
          },
        },
      },
      'x-component': 'NumberPicker',
      'x-decorator': 'FormItem',

    },
  },
};

8. 模型 inspector 工具

Formily 官方也提供了了 inspector 工具,可以查看 formily 表单每一个 Field 的内置状态,让你更好进行开发调试。

image.png

9. 拖拽开发

Formily 同样支持可视化拖拽表单开发,可以参考文档

image.png

10. 总结

表单场景一直都是前端中后台领域最复杂的场景。

Formily 是面向复杂场景的表单解决方案,提供了表单联动方案,可跨端,性能高,即便是后端,也能搭建前端表单。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYu451vF' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片