@alifd/next react+form+table组合式写法

1 篇文章 0 订阅
订阅专栏
本文介绍了在前端项目中使用@alifd/next库构建后台管理系统时,如何处理表格的三级联动、数据操作及表单验证。作者通过form包裹table,实现了表格数据的动态控制,并详细展示了如何处理单元格的编辑、删除以及保存时的校验流程。同时,文章也提出了代码复杂性的问题,探讨了field写法的可能优化。
摘要由CSDN通过智能技术生成

前言

最近前端大佬用@alifd/next来写后台管理系统,给我分配了一些页面类似下面的页面
在这里插入图片描述
其中分公司、存储地址、存储区三级联动。table中每一项都可以进行删除。添加按钮的弹框的页面类似下面这个样子。
在这里插入图片描述
点击弹框的行,多选,全选都可以进行更新到第一张图的页面

遇到的问题

  • 怎么控制这个table变化呢,怎么进行,输入框单独可以操作,下拉框单独。如果对一个数据元进行来回更改,那么页面的消耗就很大。等等问题,下面就来例举几个吧

实现

之前看了一下官方的 field关于类似方案的例子,发现写的比较简洁。也不好操作。所以我就尝试form+table组合式写法魔改了一下

1,利用form对table进行包裹,因为form内嵌了field,这样应该就比较方便一些。
   const fieldTable = Field.useField(); //初始化fieldTable
    <Form field={fieldTable}>
         <Table.StickyLock
           size="medium"
           primaryKey="id" // 识别的唯一值
           fixedHeader
           maxBodyHeight={400} //和fixedHeader结合,设置table盒子的高度
           dataSource={dataSource} //数据源
           columns={columns} // 列表
           rowSelection={rowSelection} // 选择每一行的操作,默认多选
         />
       </Form>

选择rowSelection设置

 const [selectedRowKeys, setSelectedRowKeys] = useState([]);
 const [selectedRows, setSelectedRows] = useState([]);
 const rowSelection = {
    selectedRowKeys,
    onChange: (_selectedRowKeys, _selectedRows) => { // 单选时的操作
      setSelectedRowKeys(_selectedRowKeys);
      setSelectedRows(_selectedRows);
    },
    onSelectAll: (selected, _selectedRows) => { //全选时的操作
      setSelectedRowKeys(_selectedRows.map((item) => item.cid));
    },
    getProps: (record) => { // 禁用的☑️的操作
      return {
        disabled: mode === 'view',
      };
    },
  };
2,对columns进行封装,(删除了几个重复类型的,大致能懂应该)
const columns = [
      // 新增/编辑用到的id,itemId,不显示但是可以区分(用是否有itemId来区分是点击编辑时拿到的数据,还是编辑时新增还是新增时新增的数据)
      {
        width: '0px', // 不会显示在页面
        dataIndex: 'id',
        align: 'center',
        lock: 'left',
        cell: (value, index, record) => {
          return <div style={{ display: 'none' }}>{FormChildItem(value, index, record, 'id')}</div>;
        },
      },
      {
        width: '0px',// 不会显示在页面
        dataIndex: 'itemId',
        align: 'center',
        lock: 'left',
        cell: (value, index, record) => {
          return <div style={{ display: 'none' }}>{FormChildItem(value, index, record, 'itemId')}</div>;
        },
      },
      {
        title: '类型',
        dataIndex: 'wirType',
        align: 'center',
        lock: 'left',
        cell: (value, index, record) => {
          return value ? (
            <Tag size="small" type="normal" color={wirTypeColor[value]}>
              {wirTypeName[value] || 'BTS备货'}
            </Tag>
          ) : (
            <Tag size="small" type="normal" color="turquoise">
              BTS备货
            </Tag>
          );
        },
      },
      // 下面是formItem进行嵌套的
      mode === 'add' ? isNull() : isRequireNo(), // 根据是编辑还是新增,动态显示table的列
      {
        title: '物料名称',
        dataIndex: 'itemName',
        align: 'center',
        lock: 'left',
        cell: (value, index, record) => {
          return FormChildItem(value, index, record, 'itemName');
        },
      },
      {
        title: '键号',
        dataIndex: 'itemCode',
        align: 'center',
        cell: (value, index, record) => {
          return FormChildItem(value, index, record, 'itemCode');
        },
      },
      {
        title: '申请数量',
        dataIndex: 'applyQuantity',
        align: 'center',
        cell: (value, index, record) => {
          return FormChildItemRequire(value, index, record, 'applyQuantity');
        },
      },
      {
        title: '存储区',
        dataIndex: 'areaId',
        align: 'center',
        cell: (value, index, record) => {
          return FormChildItemSelect(value, index, record, 'areaId');
        },
      },
    ];

isNull用来对三元表达式进行操作,不然写table就会报错

 const isNull = () => {
    return {
      align: 'center',
      width: '0px',
    };
  };
  const isRequireNo = () => {
    return {
      title: '订单编号',
      dataIndex: 'requireNo',
      align: 'center',
      lock: 'left',
      cell: (value, index, record) => {
        return <div>{value ? `${value}⚠️` : ''}</div>;
      },
    };
  };
3 封装的FormChildItem普通的表单显示,FormChildItemRequire可校验的InputFormChildItemSelect可校验的select。为什么要给普通FormChildItem也用表单包裹呢,主要是后端同学要用到里面的数据。要做处理,下面因该就会明白点。
  • 下面是用每一行的id来进行区分的,⚠️不要用索引index来代替,因为删除的时候会出问题
 const FormChildItem = (value, index, record, _name) => {
    return (
      <FormItem
        isPreview // 查看的时候不能修改的一个属性
        name={`${_name}-${record.id}`}
        labelAlign="left"
      >
        <Input defaultValue={value} />
      </FormItem>
    );
  };
  const FormChildItemSelect = (value, index, record, _name) => {
    return (
      <FormItem
        isPreview={mode === 'view'}
        asterisk
        name={`${_name}-${record.id}`}
        required
        requiredMessage="请选择存储区"
        labelAlign="left"
      >
        <Select style={{ width: '110px' }} defaultValue={value} dataSource={storageType} />
      </FormItem>
    );
  };
  const FormChildItemRequire = (value, index, record, _name) => {
    return (
      <FormItem
        isPreview={mode === 'view'}. 
        asterisk
        name={`${_name}-${record.id}`}
        required
        requiredMessage="请输入申请数量"
        labelAlign="left"
      >
        <NumberPicker defaultValue={value} min={0} />
      </FormItem>
    );
  };
4,既然讲到了删除,那就写一下删除的方法(新增就不写了,比较简单,弹框子组件用setDatasource来设置传值)
  // 点击删除按钮删除
  const clickDeleteDataObj = () => {
    if (!selectedRowKeys?.length) {
      Message.error('请选择物料明细进行删除');
    } else {
      const newArr = removeDuplicates(dataSource, selectedRows); //dataSource:新增时通过从弹框选中拿到的数据数组;selectedRows:第一个页面删除时拿到的行数数组
      setDataSource(newArr); // 重新设置table的源数据
      // 重置key
      setSelectedRowKeys([]); //清空被第一个页面被选中的框
    }
  };
  // removeDuplicates删除的方法, 删除table数据,通过id来删除,简单有效。
  const removeDuplicates = (arr1, arr2) => {
    const ids = new Set(arr2.map((item) => item.id));
    return arr1.filter((item) => !ids.has(item.id));
  };
5,保存的时候校验该怎么做呢?

这里做了两个表单校验,通过页面1可以观察到,顶部也是个form要进行校验,它的field名字就叫field

 // 保存草稿| 提交申请
  const handleOk = (type: number) => {
    // type 1为保存草稿,2为提交申请
    field.validate(field.getNames(), async (error) => {
      if (error === null) {
        const paramsValue: Object = field.getValues(); // 获取顶部的form数据
        if (!dataSource?.length) {
          return Message.error('请添加物料信息');
        }
        // 对table进行校验
        fieldTable.validate(fieldTable.getNames(), async (errorIn) => {
          const paramsValueIn: Object = fieldTable.getValues(); // 获取table的数据,这里获取的数据就是被FormItem包裹的数据,
          //但是拿到的是对象,而且是所有`name-id`的对象,所以下面的方法将对象变为数组
          const detailVoList = objChangeArr(paramsValueIn); // 
          if (errorIn === null) {
            let TCode = 0;
            let TMsg = '';
            if (mode === 'add') {
              // 新增,submitImmediately:保存草稿(false)和提交申请(true)
              const { code = 0, msg = '' } = await services.fetchAddReplenishmentDraftAndApply({
                ...paramsValue,
                detailVoList,
                submitImmediately: type === 2,
              });
              TCode = code;
              TMsg = msg;
            } else {
              // 编辑
              // 只需要editDataSource被标记删除的数据
              const _editDetailVoList = editDataSource.filter((v: any) => v.delete);
              console.log(_editDetailVoList, '_editDetaVoList');
              const { code = 0, msg = '' } = await services.fetchEditReplenishmentDraftAndApply({
                ...paramsValue,
                detailVoList: [...detailVoList, ...(_editDetailVoList || [])],
                submitImmediately: type === 2,
              });
              TCode = code;
              TMsg = msg;
            }
            if (TCode === 101) {
              Message.success(TMsg);
              onOk?.(); // 父组件传入的值,不用管
              field.resetToDefault();
            }
          } else {
            // console.log(error);
          }
        });
      } else {
        // console.log(error);
      }
    });
  };
  • 对象转数组
    类似这样的对象在这里插入图片描述
    转为数组在这里插入图片描述
 // 将对象转换成数组
  const objChangeArr = (obj) => {
    const _detailVoList = Object.keys(obj)
      .reduce((acc: any, key: string) => {
        const [prefix, id] = key.split('-');
        if (prefix === 'id') {
          acc.push({
            // 编辑时,在有名为itemId的前提下,拿到id,否则(编辑时新增的,新增时新增的)就不传id,
            id: obj[`itemId-${id}`] ? obj[`id-${id}`] : undefined, // 这个属于业务逻辑,不注重
            itemId: obj[`itemId-${id}`] || obj[`id-${id}`],
            itemCode: obj[`itemCode-${id}`],
            applyQuantity: obj[`applyQuantity-${id}`],
            areaId: obj[`areaId-${id}`],
          });
        }
        return acc;
      }, [])
      .filter(Boolean);
    return _detailVoList;
  };
还有其他问题
  • 1,保存,编辑时回显的被删除的数据,并打上标记delete
    可以页面初始化的时候设置另外一个datasource数据源进行保存,然后合并进去
  • 2,三级联动问题,参考第一个页面,重新选择分公司或者存储地址,table里面的数据要清空,所以我是这样写的
 // 清空所有存储区 // 这里利用dataSource来进行遍历。通过field的setValue,重新设置为空字符串来清空
  const clearAreaId = () => {
    dataSource?.map((itemClear: any) => {
      const areaIdNum = `areaId-${itemClear.id}`;
      fieldTable.setValue(areaIdNum, '');
      return itemClear;
    });
  };
后记

这么写完后,我这边功能没什么问题了,但是大佬却说我写的过于复杂,不好维护,要改成field写法,但是对于field写法,我是感觉不想写。不知道其他大佬有什么建议没有。

多多分享,快快成长。

next:React一个基于React的Web可配置组件库
02-05
@alifd/next通常与一起使用,以提高设计人员与开发人员之间的协作和开发效率。 Designer可以自定义组件的UI并发布npm主题包。 开发人员可以直接使用此主题包,而无需关心UI重构。 节省了设计人员反复进行还原度审查...
原生革命--跨平台开发技术解析
weixin_34252090的博客
05-27 1286
这篇文章,我将着重分析当前主流跨平台开发解决方案(偏架构)如Flutter、RN、Weex、Hybrid App,并对新晋跨端解决方案Fusion和Chameleon做一些分析,在传统原生开发不断被唱衰、大前端试图一统天下的今天,了解这些知识是有必要的. 目录 1.原生开发,优势与痛点分析 2.Android系统架构 3. iOS系统架构 4.跨平台开发的目的&&主流技术 5...
启动阿里低代码平台报错 error in ./node_modules/@alifd/next/es/grid/main.scss
AlgoRain的博客
03-16 423
第一次使用阿里巴巴的低代码平台,在简单绘制了几个组件后,准备导出来在本地运行起来,按照readme先安装了npm相关的包,但在启动后一直有这个报错,看了github上一些解决方式,都是让修改@alifd/next的版本,或者npm的版本,修改alifd版本后再重新启动也不管用。看了错误提示是在main.scss这个文件里有一行代码错误了。所以直接找到这个文件对应的这行,然后把这行删掉。保存以后再次启动,发现了可以了。
formtable结合
V_雨落的博客
07-26 6946
&lt;form action=""&gt; &lt;fieldset&gt; &lt;legend&gt;登录信息&lt;/legend&gt; &lt;table&gt; &lt;tr&gt; &lt;td&gt; 登录名: &lt;/
tableform的使用,以及制作登录表单
小梁说代码的博客
09-23 1959
table的简单使用 <table> <caption>表格标题</caption> <tr> <th>列名一</th> <th>列名二</th> </tr> <tr> <td>数据一</td> <td>数据二</td> </tr> </table> 效果
面试被问到低代码细节?听我这样吹(含架构和原理)
程序员成长指北
10-08 1925
大厂技术高级前端Node进阶点击上方程序员成长指北,关注公众号回复1,加入高级Node交流群写在前面❝一直以来我总是会刷到一些关于低代码的文章,但都是零零散散的,根本记不住。现在终于有时间在这里做个系统性的总结了????❞关于低代码,想必大家都有所了解,就是用拖拉拽的方式来快速搭建某个页面 || 表单 || 海报 || 游戏等,但其实除了常见拖拉拽的方式以外,还可以用形如在线文档的方式来生成页...
layout:React布局组件
05-14
@alifd/layout Layout of PC Box 参数 说明 类型 默认值 direction 布局方向可选值:'row', 'column' Enum column justify 主轴对齐方式可选值:'flex-start', 'center', 'flex-end', 'space-between', 'space-around'...
tabler-icons-react:React ReactTabler图标
04-28
表格图标React 用于的React组件库-一组超过700个免费的MIT开源许可图标。 用法 该软件包可通过npm获得,并可以使用npm或yarn安装: # npm npm install tabler-icons-react # yarn yarn add tabler-icons-react ...
react+ant design实现Table的增、删、改的示例代码
01-19
本人小白一名,第一次学习react ,该资料为本人原创,采用的是react+ant design的Tabled的一个小demo,暂时只实现了增加,删除单行,多行删除有Bug,查看详情,呕心沥血耗时一周完成,禁止抄袭,转载请先留言, ...
react移动端项目构建,react@18.2.0+react-vant+vite+axios+redux+sass
最新发布
03-06
该架构已解决大部分坑,主要用于react@18.2.0移动端,在使用项目前请确保已安装node、yarn工具,node版本18+,此项目构建主要集成:axios、vant、sass、vite、sass、react V18,其中还会介绍到如何跨页面传递数据、...
html5之table嵌入form表单布局(务必注意:table标签必须在form表单内部,不能再form表单外部!)
热门推荐
weixin_43343144的博客
03-27 1万+
切记:用table标签来布局form表单元素,table标签必须放在form表单内部,否则可能会出现各种bug <form action=""> <table > <tr> <td>姓名</td> <td><label for="">na...
webpack loader
likunpeng6656201的博客
10-05 175
https://www.jianshu.com/p/ad99b2479bee
upload 图片上传
达摩龙的博客
12-24 521
图片上传OSS上传另一种方法上传 OSS上传 import { Upload, Button, Icon } from ‘@alifd/next’; <Form.Item label=“操作说明图片”> </Form.Item> // 图片上传 const beforeUpload = (file, options) => { if (file.size > 2048000) { Message.error(‘文件不能大于2M’); return false;
form表单多层数据结构校验以及form表单和table表格校验结合完整案例,超级详细,直接复制粘贴,拿来就用
jieweiwujie的博客
10-10 2164
form表单和table表格校验,多层数据结构
form表单多层数据结构校验以及form表单和table表格校验结合完整案例,超级详细,直接复制粘贴,拿来就用(二)
jieweiwujie的博客
12-01 616
el-element的表单和表格一起校验写法
【web前端基础day02】表格table+表单form
qq_61971608的博客
01-16 4262
HTML over
阿里巴巴官方低代码引擎开源!快速交付的神器
HollisChuang's Blog
02-12 1401
LowCodeEngine是由阿里巴巴钉钉团队开源的低代码引擎, 该引擎全面遵循《阿里巴巴中后端前端基础构建协议规范》和《阿里巴巴中后端前端素材协议规范》。兼容主流浏览器:Chrome >= 80,Edge >= 80,safari和firefox 最近 2 个 版本。特性•???? 提炼自企业级低代码平台的面向扩展设计的内核引擎,奉行最小内核,最强生态的设计理念•???? 开箱即用的高...
细数阿里 25 个开源的前端项目
xuehu837769474的博客
03-12 5241
内容简介:AntVG2 是一套基于可视化编码的图形语法,以数据驱动,具有高度的易用性和扩展性,用户无需关注各种繁琐的实现细节,一条语句即可构建出各种各样的可交互的统计图表。 数据驱动的高交互可视化图形语法 AntV - G2 AntV G2 是一套基于可视化编码的图形语法,以数据驱动,具有高度的易用性和扩展性,用户无需关注各种繁琐的实现细节,一条语句即可构建出各种各样的可交互的统计图表。...
表单组件数据到接口参数的数据结构转换
沐唐风宋雨
08-06 513
实际开发过程中,表单数据的数据结构与接口参数需要的数据结构往往存在些许差异,此时就需要一对一进行转化,那么如何做才显得优雅呢? 举个例子: { "select": "jack", "startDate": "2020-07-31T16:00:00.000Z", "endDate": "2020-07-31T16:00:00.000Z", "select": [ "a", "b" ], } { "select": "jack", "startDate": "2020-07-31 16:
为什么 @types/react-redux 会下载最新版本的@types/react
07-20
@types/react-redux 是一个用于 TypeScript 的声明文件库,它提供了与 react-redux 库一起使用的类型定义。当你安装 @types/react-redux 时,它会自动依赖于最新版本的 @types/react。 这是因为 react-redux 库本身可能使用了最新版本的 react 类型定义,为了确保类型的兼容性和正确性,@types/react-redux 会使用与 react 版本匹配的类型定义。这样可以确保在使用 react-redux 时,类型检查和代码提示能够正常工作。 因此,当你安装 @types/react-redux 时,它会下载与你项目中已安装的 react 版本相匹配的最新版本的 @types/react。这样可以确保在编写代码时能够正确地使用 react-redux 库的类型定义。
写文章

热门文章

  • 基于umijs/plugin-qiankun 的微前端 配置(vue+umi) 9630
  • antd upload上传格式.doc、.docx、.pdf、.png、.jpg、.rar和大小100兆限制 8483
  • github在线查看代码&运行的方法 8165
  • mac终端查看ssh 7818
  • node.getIterator is not a function 6654

分类专栏

  • react项目问题汇总 1篇

最新评论

  • github在线查看代码&运行的方法

    李铁头头铁: 什么时候会出现open brower?博主

  • github在线查看代码&运行的方法

    2301_79780021: 我也是要美国号码哈哈哈

  • node.getIterator is not a function

    一只夏宇坤: 应该不用修改代码,vant样式做了隔离的,应该不影响。你可以试一下

  • node.getIterator is not a function

    toto11luv: 你好 请问这个可以适配vant组件库吗 需要修改一下代码吗

  • github在线查看代码&运行的方法

    一只夏宇坤: 不用啊,我能正常打开啊表情包,是不是网络原因

大家在看

  • 代码随想录训练营第66天|Floyd
  • 商云8前台销售最大数量9999
  • 代码随想录训练营第65天|bellman_ford应用 101
  • 【Python入门】5步轻松掌握Python源码打包:你真的会了吗?
  • MySQL 一致性视图(MVCC) 330

最新文章

  • 你应该知道的关于Object的一些方法
  • the “@esbuild/darwin-x64“ package is present but this platform needs the “@esbuild/darwin-arm64“
  • 前端浅拷贝和深拷贝
2023年8篇
2022年11篇
2021年1篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只夏宇坤

你的鼓励是我持续创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家商场圣诞美陈布置用途玻璃钢向日葵雕塑价格玻璃钢雕塑室外能用多久徐州玻璃钢人物雕塑价格四川装饰商场美陈制作重庆卡通人像玻璃钢雕塑商场瓷砖美陈玻璃钢雕塑定制尺寸表银川玻璃钢雕塑圆雕广东超市商场美陈销售河北户外玻璃钢雕塑销售电话合肥定制玻璃钢雕塑厂家濮阳花朵玻璃钢雕塑价格福建小区玻璃钢雕塑生产厂家嘉兴玻璃钢雕塑陈设贵州景观玻璃钢雕塑优势黔南州商场美陈报价遵义玻璃钢雕塑制作哪家好东莞时尚玻璃钢面包雕塑南昌玻璃钢考拉雕塑定制玻璃钢雕塑人物哪家有铜陵动物玻璃钢雕塑优势玻璃钢无人机雕塑工业玻璃钢雕塑摆件售价枝江玻璃钢仿铜雕塑昆山玻璃钢雕塑联系方式户外商场美陈销售企业玻璃钢动物雕塑价格品牌武汉商业广场玻璃钢卡通雕塑价格六安多彩玻璃钢雕塑定制香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化