本文主要介绍formilyjs,它是阿里统一的前端表单解决方案。具有比较完善的表单设计和复杂的场景处理功能。当然,本文主要介绍其窗体设计和展示功能,并将其应用到我们的流程可视化自定义编辑中。至于formilyjs自定义开发控件,后面会有单独的章节来讲解。可设计的可视化表单设计formilyjs官网提供了Formilydesigner。现在我们把表单设计器拉下来,变成我们的一个页面:新建一个src/playground目录,yarnadd@designable/formily-antd@ant-design/pro-components到设计器github,复制相关文件在playground和src目录下放到playground/details,并调整引用结构(略过,看代码)。//routes{name:'FormTemplate',path:'/playground',icon:'FormOutlined',component:'@/pages/playground',},{name:'FormDesign',path:'/playground/details',component:'@/pages/playground/details',headerRender:false,footerRender:false,menuRender:false,hideInMenu:true,},表单模板列表新建playground/index.tsx和playground/Preview.tsx,前者用作新的表单模板,后者是表单设计后的预览//playground/index.tsximporttype{ActionType,ProColumns}from'@ant-design/pro-components';import{ProTable}from'@ant-design/pro-components';import{PageContainer}from'@ant-design/pro-layout';import{FormItem,Input,FormDialog,FormLayout}from'@formily/antd';import{createSchemaField}from'@formily/react';import{Dropdown,Menu,Popconfirm,Space,Button}from'antd';import{FC,useRef,useState}from'react';importPreviewfrom'./Preview';import{LgetItem,LsetItem}from'@/utils/storage';从'@a导入{uuidv4}ntv/xflow';import{history}from'umi';constSchemaField=createSchemaField({components:{FormItem,Input,},});constschema={type:'object',properties:{name:{type:'string',title:'模板名',required:true,'x-decorator':'FormItem','x-component':'Input',},},};const游乐场:FC=()=>{const[modalConfig,setModalConfig]=useState<{[key:string]:任何}>({});constpreviewRef=useRef<{setVisible:(flag:boolean)=>void}>(null);constactionRef=useRef();constcolumns:ProColumns[]=[{dataIndex:'name',title:'模板名',},{dataIndex:'params',title:'是否配置',renderText(text,record,index,action){返回文本?'是':'否';},search:false,},{title:'操作',valueType:'option',render:(_,record)=>{return[{setModalConfig(记录);previewRef.current?.setVisible(true);}}>预览,handleEdit(record)}>配置,handleDel(记录)}>删除,];},},];consthandleEdit=(record:any)=>{history.push(`/playground/details?id=${record.id}`);};consthandleDel=(record:any)=>{constplaygroundList=LgetItem('playgroundList')||[];LsetItem('playgroundList',playgroundList.filter((s)=>s.id!==record.id),);actionRef.current?.reload();};consthandleAdd=()=>{FormDialog('新增模板',()=>{return();})。为了Open((payload,next)=>{next({initialValues:{name:'',},});}).forConfirm((payload,next)=>{constplaygroundList=LgetItem('playgroundList')||[];playgroundList.push({name:payload.getFormState().values.name,id:uuidv4(),});LsetItem('playgroundList',playgroundList);actionRef.current?.reload();next(payload);}).forCancel((payload,next)=>{next(payload);}).open().then(console.log);};constgetData=async(params:any)=>{constdata=LgetItem('playgroundList');返回{数据:数据??[],成功:true,总计:data?.length??0,};};return({返回等待getData(参数);}}rowKey="id"pagination={{showQuickJumper:true,}}toolBarRender={()=>[新增,]}/>);};exportdefaultPlayground;//playground/Preview.tsximport{FC,Ref,useEffect,useImperativeHandle,useState}from'react';import{Modal}from'antd';import{FormItem,Input,Form,Submit,ArrayBase,ArrayCards,ArrayCollapse,ArrayItems,ArrayTable,ArrayTabs,BaseItem,Cascader,Checkbox,DatePicker,Editable,FormButtonGroup,FormCollapse,FormGrid,FormTab,GridColumn,NumberPicker,Password,PreviewText,Radio,Reset,Select,SelectTable,Space,Switch,TimePicker,Transfer,TreeSelect,Upload,}from'@formily/antd';从'@formily/antd'导入*作为aaa;从'@formily/react'导入{createSchemaField};从'@/utils/storage'导入{LgetItem};从'@formily导入{createForm}/core';console.log(aaa);interfacePreviewProps{previewRef:Ref<{setVisible:(flag:boolean)=>void}>;modalConfig:{[key:string]:any};}constSchemaField=createSchemaField({组件:{Input,ArrayBase,ArrayCards,ArrayCollapse,ArrayItems,ArrayTable,ArrayTabs,BaseItem,Cascader,Checkbox,DatePicker,Editable,Form,FormButtonGroup,FormCollapse,FormGrid,FormItem,FormTab,GridColumn,NumberPicker,Password,PreviewText,Radio,Reset,Select,SelectTable,Space,Submit,Switch,TimePicker,Transfer,TreeSelect,Upload,},});常量预览:FC=({previewRef,modalConfig})=>{const[visible,setVisible]=useState(false);useImperativeHandle(previewRef,()=>({setVisible,}));const[params,setParams]=useState({});constnormalForm=createForm({});useEffect(()=>{if(modalConfig&&visible){constplaygroundList=LgetItem('playgroundList')||[];constdata=playgroundList.find((s)=>s.id===modalConfig.id);setParams(data?.params||{});}},[modalConfig,visible]);consthandleCancel=()=>{setVisible(false);};返回(Save);};exportdefaultPreview;这里我们简单的将创建好的表单数据存储在本地localStorage中,点击Configure跳转到我们的设计页面,调整表单设计的保存,我用设计拖拽设计完成后,存储数据,找到id对应的表单模板,将设计好的schema赋值给params//details/service/schema.tsimport{Engine}from'@designable/core';import{transformToSchema,transformToTreeNode,}来自'@designable/formily-transformer';import{message}from'antd';import{LgetItem,LsetItem}from'@/utils/storage';functionfixUrlHash(url:string){letfixedUrl=newURL(url);letsearch=fixedUrl.search;lethash=fixedUrl.hash;constposition=fixedUrl.hash.indexOf('?');if(search.length<=1&&position>=0){search=hash.slice(position);hash=hash.slice(0,position);fixedUrl.hash=hash;fixedUrl.search=搜索;fixedUrl.href=fixedUrl.toString();}returnfixedUrl;}exportconstsaveSchema=(designer:Engine)=>{consturl=fixUrlHash(window.location.href);constsearchParams=newURLSearchParams(url.search);让playgroundList=LgetItem('playgroundList')||[];playgroundList=playgroundList.map((s)=>{if(s.id===searchParams.get('id')){返回{...s,参数:transformToSchema(designer.getCurrentTree()),};}返回s;});LsetItem('playgroundList',playgroundList);message.success('保存成功');};exportconstloadInitialSchema=(designer:Engine)=>{consturl=fixUrlHash(window.location.href);constsearchParams=newURLSearchParams(url.search);常量playgroundList=LgetItem('playgroundList')||[];constdata=playgroundList.find((s)=>s.id===searchParams.get('id'));试试{designer.setCurrentTree(transformToTreeNode(data?.params||[]));}抓住{}};然后回到模板列表页面,点击预览,看看我们设计的表单是否正常显示。下一章会介绍表单设计器的一些高级配置,比如动态请求、封装接口注入、表单联动配置等,敬请期待本文地址:本文github链接地址:链接github演示地址:链接