表单设计器的困扰

起源

年前接手一个项目使用时需要动态设计表单,那么显然需要一个表单设计器,公司主要使用框架是vue所以能找到的表单设计器就有:avue、formMaking、variantfrom ...等,又因为需求中需要组件联动如: 组件之间控制展示隐藏、Select等组件源动态加载不同的远程数据、还需要组件可以自由扩展...显然前边几个设计器都不符合要求,自己动手撸一个又太花时间成本又不允许,领导拍板改avue源码做一个。

吐槽一下,说实话avue的源码一言难尽 几乎没有设计可言

经历

从此痛苦开始了...

  • 修改嵌套树结构 (组件递归节点过多易卡死.)
  • 控制组件需提升数据至父组件(组件被控制会导致函数多次重复计算)
  • 被控制组件的数据是否仍需保留
  • 自定义组件添加
  • 最后保存的组件json结构臃肿,内置大量需执行字符串函数、bug排查困难
  • ....

经过一番痛苦折磨后最终完成并上线了,但是效果并不好用起来不流畅,且维护困难。

思考

查过很多表单设计器源码后发现都是大差不差的内容,为什么表单设计器都这么难用?难以维护的痛点都在控制逻辑代码与显示代码数据转换代码都混在一起,可不可以清晰一点。并且打包体积很大表单设计器修改一次整个前端项目都需要发版,想到可以用微前端方法拆分出来,就在这个时候也突然想到了formily

微前端

独立开发、独立部署微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新。

formily

一个古老的表单json表单方案,formily可以轻松做到组件之间联动、嵌套、布局等问题仅需一个json结构、缺点是formily的上手需要一点点的学习成本,并且formily有内置的表单设计器!!简直吕布见到貂蝉的感觉,这不就是我想要的。

设计器单独部署解决维护设计器时项目需要一起发版问题,并且微前端方案完美解决vue项目与react项目同时使用

formily设计器扩展

formily扩展自定义组件还是比较容易的,但是设计器代码里添加自定义的组件找了很久官方也没有文档、资料也比较难查最后经过翻查源码还是被我解决了。哈哈哈!

补刀,formily设计器的源码设计就挺强的~

formily设计器添加自定义组件

官方地址 源码自行下载 formilyjs.org/zh-CN/guide...

建议:自己搭建一个react项目只安装设计器就可以了 怎么搭建react项目我就不贴出来了,我这里是用vite + react18创建一个空项目

安装设计器

npm install --save @designable/formily-antd
这里会有小伙伴安装后出现跑不起来的情况,建议照着官方示例源码把需要的文件全部复制过来,如果出现less问题就安装less,或者还会有文件地址找不到的情况,我这里用的是vite所以修改一下vite的文件路径别名对应一下就可以了,如果有其他问题可以给我留言

  1. 创建自定义组件

根路径创建 custom-compoent文件夹放置自定义的组件

组件内容很简单

js 复制代码
// props中将来会传进来 value disabled readonly onChange方法等内置属性用来控制组件
// change(xxxx) 执行change方法就可以变更value值,value默认会是undefined
// 需要在设计器右侧属性控制栏添加的属性也会在props中传进来
 export const Uploda = (props:any)=> {
   console.log(props)
   
   return <Button>
     UploadShowTable
   </Button>
}

我这里的外层index仅仅是做了统一导出

js 复制代码
export * from './UploadShowTable'

2.添加组件行为属性 components中新增自定义的组件并添加属性,照着其他组件抄就可以仅需把导出的名称做个修改 也跟也一样prview导出index导出等统一一下

js 复制代码
// designerLocales 国际化语言这里可以直接中文或者也可以照着其他组件一样ctrl c v 改ok了
// designerProps 组件的属性控制源
import React from "react";
import { UploadShowTable as FormilyUploadShowTable } from '@/componentCustom'
import { createBehavior, createResource,GlobalRegistry } from "@designable/core";
import { DnFC } from "@designable/react";
import { createFieldSchema } from "../Field";
import { AllSchemas } from "@/core/schemas";
import { AllLocales } from "@/core/locales";

export const UploadShowTable: DnFC<React.ComponentProps<typeof FormilyUploadShowTable>> = FormilyUploadShowTable;

UploadShowTable.Behavior = createBehavior(
  {
    name: "UploadShowTable",
    extends: ["Field"],
    selector: (node) => node.props["x-component"] === "UploadShowTable",
    designerProps: {
      propsSchema: createFieldSchema(AllSchemas.UploadShowTable),
    },
    designerLocales: AllLocales.UploadShowTable,
  }
);


UploadShowTable.Resource = createResource(
  {
    icon: "UploadSource",
    elements: [
      {
        componentName: "Field",
        props: {
          type: "Array<object>",
          title: "UploadShowTable",
          "x-decorator": "FormItem",
          "x-component": "UploadShowTable",
          "x-component-props": {
            textContent: "UploadShowTable",
          },
        },
      },
    ],
  }
);

3.添加国际化

locales下文件夹一样照样画葫芦CV一个并且修改title,依次都导出即可。

4.自定义组件的控制属性 core/schemas 这里配置的内容就是属性栏的属性,结构就和schema表单一模一样,直接写就行了。 记得也一样都导出

js 复制代码
import { ISchema } from '@formily/react'

export const UploadShowTable: ISchema = {
  type: 'object',
  properties: {
    textContent: {
      type: 'string',
      'x-decorator': 'FormItem',
      'x-component': 'Input',
    },
    action: {
      'x-decorator': 'FormItem',
      'x-component': 'ValueInput',
      'x-component-props': {
        include: ['TEXT', 'EXPRESSION'],
      },
    },
    name: {
      type: 'string',
      'x-decorator': 'FormItem',
      'x-component': 'Input',
      'x-component-props': {
        defaultValue: 'file',
      },
    },
    ....
  }
 }
  1. 注册自定义的组件

设计器的主页面 ResourceWidget 和 ComponentTreeWidget 组件中添加自定义的行为方法

js 复制代码
  ....
  Space,
  FormTab,
  FormCollapse,
  FormLayout,
  FormGrid,
  + UploadShowTable,
} from "@/components";
...
...
<ComponentTreeWidget
    components={{
      Form,
      + UploadShowTable
      ...
      
...
<ResourceWidget
              title="sources.Inputs"
              className="bg-white"
              sources={[
                Input,
                + UploadShowTable
                ...
                
...

最后 MarkupSchemaWidget、PreviewWidget 中都注册自定义的组件

js 复制代码
...
+ import { UploadShowTable } from '@/componentCustom'
...
const SchemaField = createSchemaField({
  components: {
    Space,
    FormGrid,
    +UploadShowTable
    ...

大功告成!

相关推荐
kyriewen4 小时前
百度用6%成本碾压硅谷?中国AI把性价比玩明白了
前端·百度·ai编程
kyriewen4 小时前
你还在手动敲命令部署?GitHub Actions 让你 push 即上线,摸鱼时间翻倍
前端·面试·github
Csvn6 小时前
Pinia 状态管理
前端
不减20斤不改头像6 小时前
手机一句话开发贪吃蛇!TRAE SOLO 移动端 AI 编程实测
前端·后端
xuankuxiaoyao6 小时前
Vue.js实践-组件基础下
前端·javascript·vue.js
一棵白菜6 小时前
Claude Code + Amazon Bedrock 使用指南
前端
大家的林语冰7 小时前
前端周刊:axios 疑遭朝鲜黑客“钓鱼“;CSS 新函数上线;npm 上线深色主题;Oxlint 兼容表;ESLint 支持 Temporal......
前端·javascript·css
哀木8 小时前
一个简单的套壳方案,就能让你的 Agent 少做重复初始化
前端
问心无愧05138 小时前
ctf show web入门27
前端
自小吃多8 小时前
本地部署大模型避坑实录|Ollama+AnythingLLM 一直加载、CPU 爆满、GPU 闲置问题完整解决
笔记