100 左右实现查询表格?真的假的?一起来体验一下 Amiya 的魅力。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
viewweiwu
V2EX    分享创造

100 左右实现查询表格?真的假的?一起来体验一下 Amiya 的魅力。

  •  1
     
  •   viewweiwu
    viewweiwu 2022-03-01 11:16:45 +08:00 4067 次点击
    这是一个创建于 1390 天前的主题,其中的信息可能已经有所发展或是发生改变。

    image.png

    “老哥,听说你写的页面挺多的,我这儿有一个页面,你觉得你需要多少代码?”

    “我看看,也还行吧,不就是个查询表格嘛,现在大家都用 ProComponent 了,用那个写一下很快的。我想想,差不多 200 行左右就可以了吧。”

    “那个呀,我知道,官方的二次封装组件库,200 行就可以了吗?嗯,可以。等等,你说的代码是否包含了操作按钮?”

    “操作按钮?是指你图上的 [新增] [详情] 这些按钮吗?”

    “是啊。”

    “点了之后长啥样呀,你也没给我看呀!”

    “哦,差不多长这个样。”

    image.png

    “哦~ 这样子啊,那这个简单,不就是个弹窗表单嘛,撑死再加个 100 行吧。”

    “那 [删除] 呢?”

    image.png

    “就这。10 行就搞定了吧。”

    “哈哈,你别着急嘛,还有批量删除呢!”

    image.png

    “哦哦,这也没多难啊,大部分都是表格自带的 Api,删除完刷新下表格请求就完事儿了。无非就是记录下选项嘛,再给个 10 行我觉得就差不多了。不过我看你这勾选之后,页面下面还有个条,把 [批量删除] 按钮放那里了,有点意思,不过也没多难,再加个 20 行左右我觉得差不多了。”

    “哈哈,是的,我算算,这差不多已经 340 行了吧。”

    “是啊,写这样一个页面的话,这点代码量很正常。”

    “那如果翻页后,仍然保留上个页面的选项呢?”

    “这个呀,现在哪有人做这个呀,这都是现成的组件,你不嫌麻烦我还嫌麻烦呢,而且又不是必须的,爱谁谁做。”

    “你就说你会不会吧!”

    “你是故意找茬是吧!再说了,这也不难,antd 表格不是有个 preserveSelectedRowKeys 属性吗,我觉得可以用那个实现,或者监听下表格的选择事件,存个变量就好了。实在不行,就点页面单个删除呗,也没多麻烦吧。”

    “说是这么说,确实也没必要,但我觉得有更好,如果要删除多个的话,每次删除总是要多点几次,而且删除完之后,数据不是没了嘛,那第二页的数据就会跑到第一个页面来,就会担心自己会不会删错。”

    “还行吧,只要你不嫌累,你就写吧。我觉得也没啥,如果真要做,用那个 api 就好了,顶多再加个 20 行吧。”

    “哦!对了,我忘记说了,这个数字悬浮上去是能看到选项的。”

    image.png

    “...你玩的还挺花,数据都有,搞个 Popover 套一下,就可以了吧。”

    “是的,这么样一算的话,差不多有 400 行代码了吧。”

    “嗯,你需求多嘛,差不多差不多。”

    “哈哈,这个页面我总共花了 134 行代码,你觉得可行

    “???你怎么做到的,给我看看。“

    查看表格示例代码

    “我看了一下,有意思,这个组件用了一个大 json ,把配置传进去了是吧,这种封装还挺常见的。”

    “是的,你看这是其中一个片段,表格的顶部查询,只需要指定 search: true 就可以了。”

    { title: '英文名', key: 'en' search: true } 

    “这样子啊,那上面我看有 placeholder 呀,怎么没看你传进去。”

    “哦,那个是自动生成的,像这里,会生成"请输入英文名"。”

    “那如果要自定义呢?”

    “当然也可以,需要这样子写。”

    { title: '英文名', key: 'en' search: { placeholder: '请输入英文名' } } 

    “哦~ 这还能是个对象是吧,那如果上面是个选择框呢?”

    “也简单,添加 optionstype: 'select' 就可以了。”

    { title: '职业', key: 'class', type: 'select', options: [ { label: '近卫干员', value: '1' }, { label: '狙击干员', value: '2' }, { label: '术师重装', value: '3' }, { label: '医疗干员', value: '4' }, { label: '重装干员', value: '5' }, { label: '辅助干员', value: '6' }, { label: '特种干员', value: '7' }, { label: '先锋干员', value: '8' } ], search: true } 

    “你这 optionstype 为什么没有放在 search 对象里面的呀?”

    “哈哈,这你就不知道了吧,因为这样子写的话,表格也可以用这个配置,写在 search 对象里面的话,就只能查询区域自己用了。”

    “表格也可以用这个配置?表格要这俩有啥用。”

    “表格这一列,可以通过 options 翻译,假如数据是个 1,那么这一列就会根据 options 去寻找这个 label,这时候对应的 label近卫干员,所以页面上显示的就是 近卫干员。另外如果表格有筛选,添加 filter: true 就会出现筛选了。”

    image.png

    “可以,还挺方便的,那 type 呢?这东西表格用不到吧。”

    “是的,这个的话,其实是给 dialog 弹窗编辑用的。这样子的话可以让弹窗里面也展示一个选择框了。”

    { title: '职业', key: 'class', type: 'select', options: [ { label: '近卫干员', value: '1' }, { label: '狙击干员', value: '2' }, { label: '术师重装', value: '3' }, { label: '医疗干员', value: '4' }, { label: '重装干员', value: '5' }, { label: '辅助干员', value: '6' }, { label: '特种干员', value: '7' }, { label: '先锋干员', value: '8' } ], search: true, + dialog: true } 

    “哦哦!明白了,指定了 dialog: true 后,就会在弹窗里面显示了是吧。”

    “是的,那如果只在弹窗里展示,而表格不展示呢?”

    “那可以这样子做。指定 table: false 就可以了。”

    { title: '职业', key: 'class', type: 'select', options: [ { label: '近卫干员', value: '1' }, { label: '狙击干员', value: '2' }, { label: '术师重装', value: '3' }, { label: '医疗干员', value: '4' }, { label: '重装干员', value: '5' }, { label: '辅助干员', value: '6' }, { label: '特种干员', value: '7' }, { label: '先锋干员', value: '8' } ], dialog: true, + table: false } 

    “明白了。这是把弹窗、表格、查询揉在一起了是吧,对了,我怎么没有看到新增打开弹窗的代码呢?”

    “那个呀,那个需要再加点代码。把 addApi 作为请求接口传进去,再指定 action="add" 就好了?”

    <AySearchTable title="Amiya 增删改查" dialogFormExtend={{ fields: fields, addApi }} > <AyAction action="add">新增</AyAction> </AySearchTable> 

    “这也可以?为什么?难到不需要监听按钮点击事件,然后控制弹窗显示,再请求接口,之后关闭弹窗刷新页面吗?”

    “是的,这里默认认为弹窗和表格共用一个配置,且弹窗新增大多都是千篇一律的,所以把所有的操作封装了一下,就只剩下这么点了。当然如果太过复杂,或者跟表格都没有什么可以共用的列,就再定义一个 'fields: dialogFields',和表格完全分开用俩 fields,各用各的。”

    “哦哦,可以可以,那我理解了,修改也是同理吧。”

    “是的,编辑的时候,不是会有默认值吗?此时我们把 record 传进去,当作表单的默认值就可以了。”

    const ctrl: AyTableCtrlField = { render: (value: string, record: Record) => { return ( <AyCtrl> <AyAction record={record} action="update"> 编辑 </AyAction> </AyCtrl> ) } } <AySearchTable title="Amiya 增删改查" dialogFormExtend={{ fields: fields, addApi }} /> 

    “可以,可以!这个组件把常用的操作都变成指令了啊。”

    “是的呀,如果你的详情是需要请求接口的,那就不需要 record 了,删掉之后改成 detailApidetailParams, 分别是请求的接口和请求的参数,action="view" 指令会自动的把请求返回的数据,作为打开弹窗后表单的默认值的。”

    <AyAction detailParams={record.sort_id} detailApi={detailApi} action="view">详情</AyAction> 

    “明白了,非常的棒!对了你刚刚还说到分页删除了,用这个组件是不是也很简单啊?”

    “是的,我给你看一下,这个多个几步,第一步,先添加 selectiOnType="checkbox" 开启勾选;第二步,添加 selectShowKey="cn",让气泡悬浮时用它来决定展示选中的名称,并用 tag 标签裹住,因为 tag 标签可以删除的,这样子翻页之后也可以点击 tag 标签上面的 X ,来取消选项,不用再翻到上一页取消选择了;第三步,在删除按钮上添加 action="delete" 属性,批量删除上添加 action="batch-delete" 属性,标签上添加 deleteApi={deleteApi} 接口,就可以完成删除和批量删除的动作了。”

    const ctrl: AyTableCtrlField = { render: (value: string, record: Record) => { return ( <AyCtrl> <AyAction record={record} action="delete"> 删除 </AyAction> </AyCtrl> ) } } <ySearchTable title="Amiya 增删改查" selectiOnType="checkbox" rowKey="sort_id" ctrl={ctrl} selectShowKey="cn" deleteApi={deleteApi} > <AyAction action="batch-delete">批量删除</AyAction> </AySearchTable> 

    “哦哦,这样子就可以了吗?那还挺方便的,毕竟不需要自己写一堆代码来写。对了,我刚才看了下代码,上面有个 renderType: 'html',这是什么作用。”

    { title: '描述', key: 'feature', width: 200, renderType: 'html' } 

    “你猜猜?”

    “把这一列渲染成 html 之类的?”

    “是呀,除此之外,还有 unit datetime state 等等类型,你可以看看这个。”

    查看自定义类型

    “可以,那如果我要的这里面没有呢?”

    “就等着你问这个呢,看来你用过其它的二次封装呀,这个组件提供两种方式,第一种可以指定 render 方法。”

    { title: '姓名', key: 'cn', search: true, dialog: { required: true }, table: { // 渲染自定义内容 render: (text: string, record: Record) => { return ( <div> <div>{record.cn}</div> <div>{record.en}</div> <div>{record.jp}</div> </div> ) } } }, 

    “第二种,可以全局注册,注册完之后,可以像 renderType: 'star' 这样子使用。”

    import { registerTableRender, RenderProps } from 'amiya' /** * @decs 注册 renderType * @param renderTypeName string 注册类型名字 * @param text string 当前 col 的数据 * @param record object 当前 row 的数据 * @param field 当前配置配置项 * * @returns ReactNode */ registerTableRender('renderTypeName', ({ text, record, field }: RenderProps) => { return <span>{text}</span> }) // 实际使用 const fields = [ { renderType: 'renderTypeName' // 已经注册过后的名字 } ] 

    注册自定义表单类型

    “好家伙,这跟我直接 render 也没什么区别嘛,不过用注册的方法,把 render 写在其它公共的地方的话,确实会让当前页面干净一点。”

    “是的,两种方式自由选择。你看这样子一套下来,你看,是不是省了很多代码,如果你用 jsx 语法糖的话会更省,那样子只需要 90 行代码了。”

    “对哦,我见到的其它二次封装就是少了这个,都用 json ,用起来编辑器右边空白一大片,代码又拉的老长,挺不爽的,你这样子写法我挺喜欢的,我跟他们提建议,他们都不听的,还云云这样容易控制什么的。”

     <AyFields> <AyField title="头像" key="icon" width={80} align="center" renderType="image" /> <AyField title="姓名" key="cn" search /> <AyField title="英文名" key="en" search dialog table={false} /> {// ...} </AyFields> 

    “真能省,还没见过这么能省的,不过,这个组件封装的这么多,别人会用吗?用的明白吗?”

    “确实,如果不介绍介绍的话,没人用的明白。所以这个组件支持完整的 TypeScript 提示,也准备了文档,详细地介绍了表格的使用方式,你看左侧那一堆菜单,都是在介绍表格 api 的。”

    image.png

    “而且,也有完整的页面级别的示例,也可以做参考。”

    表格其它示例

    “我看到了,这是个二次封装的组件库吧,我看还有其它组件,等我回头用用看体验一下。”

    “好的,等你消息。”

    Amiya 二次封装文档地址

    37 条回复    2022-03-09 13:42:37 +08:00
    efaun
        1
    efaun  
       2022-03-01 11:20:02 +08:00
    好家伙, 推广都得写小作文了?
    viewweiwu
        2
    viewweiwu  
    OP
       2022-03-01 11:50:21 +08:00
    @efaun 才疏学浅,随便写写
    est
        3
    est  
       2022-03-01 12:05:23 +08:00
    VB 里做双向绑定带搜索分页插入编辑的表格,一行代码都不需要写。水晶报表一个控件搞定。
    hades97
        4
    hades97  
       
    这种二次封装的 crud 组件,你们的文档算是写的清晰的
    rekulas
        5
    rekulas  
       2022-03-01 13:07:55 +08:00
    推广对话有点意思,期待下一波推广走漫画流
    cheng6563
        6
    cheng6563  
       2022-03-01 13:57:12 +08:00
    我以为是 100 块
    viewweiwu
        7
    viewweiwu  
    OP
       2022-03-01 14:13:56 +08:00
    3dwelcome
        8
    3dwelcome  
       2022-03-01 14:24:02 +08:00
    我觉得楼主方向不对,市面上对二次封装需求量很少。

    应该把表格控件的开发目标,定位在 notion 通用组件上。

    能玩出花。
    summer2019
        9
    summer2019  
       2022-03-01 14:25:50 +08:00 via iPhone
    玩的挺花,mark 一下
    sanggao
        10
    sanggao  
       2022-03-01 14:31:50 +08:00
    有 amis 好用不?
    viewweiwu
        11
    viewweiwu  
    OP
       2022-03-01 14:44:39 +08:00
    @3dwelcome 感谢你的建议,我会尝试开发更多的通用组件的。另外市面上二次封装也不少,antd 自己就有一片天地,pro components 、sula ,也有很多的呢。
    viewweiwu
        12
    viewweiwu  
    OP
       2022-03-01 14:52:10 +08:00
    @sanggao 我不知道,感觉方向不一样,amiya 只做了 antd 的封装,在保证可维护性的前提下,进行封装。如果有机会你可对比使用下,期待你的反馈。
    viewweiwu
        13
    viewweiwu  
    OP
       2022-03-01 14:54:30 +08:00
    @est 封装市场应该是多样化的,百家齐放,各取所需,如果你觉得一行代码都不用写更适合你现在场景话,那你就应该继续用下去。
    viewweiwu
        14
    viewweiwu  
    OP
       2022-03-01 14:55:32 +08:00
    @hades97 感谢认可! CRUD 只是其中一部分,这次只介绍了表格,下次会介绍下其它的组件。
    viewweiwu
        15
    viewweiwu  
    OP
       2022-03-01 15:00:28 +08:00
    @rekulas 是吗,漫画会更有意思吗?也许我可以试试
    viewweiwu
        16
    viewweiwu  
    OP
       2022-03-01 15:00:47 +08:00
    @xzb0797 感谢支持
    aitaii
        17
    aitaii  
       2022-03-01 16:20:30 +08:00
    什么游戏
    C603H6r18Q1mSP9N
        18
    C603H6r18Q1mSP9N  
       2022-03-01 18:15:35 +08:00
    很赞
    lizhesystem
        19
    lizhesystem  
       2022-03-01 19:09:51 +08:00
    我记得有个基于 element 的,AVUE 也是封装了 CRUD ,这东西挺适合搬砖的
    EscYezi
        20
    EscYezi  
       2022-03-01 19:31:04 +08:00 via iPhone
    看见 Amiya 就点进来了,果然
    viewweiwu
        21
    viewweiwu  
    OP
       2022-03-01 20:40:33 +08:00
    @EscYezi 果然啥?
    EscYezi
        22
    EscYezi  
       2022-03-01 20:46:22 +08:00 via iPhone   1
    @viewweiwu #21 博士,代码还没写完,现在还不能休息哦
    litmusF
        23
    litmusF  
       2022-03-01 20:47:51 +08:00
    类似于百度 amis
    litmusF
        24
    litmusF  
       2022-03-01 20:48:53 +08:00
    antd 有一个 sula 现在还是 beta 版本不完善 https://sula.vercel.app/
    FightPig
        25
    FightPig  
       2022-03-01 20:55:54 +08:00
    这写的 666 啊
    viewweiwu
        26
    viewweiwu  
    OP
       2022-03-01 21:00:23 +08:00
    @2218675712 SULA 我也关注很久了,那个确实也挺不错的。
    viewweiwu
        27
    viewweiwu  
    OP
       2022-03-01 21:01:01 +08:00
    @EscYezi 之前 Amiya 的 Dialog 弹窗组件就是显示的这句话,哈哈。
    viewweiwu
        28
    viewweiwu  
    OP
       2022-03-01 21:01:31 +08:00
    @FightPig 感谢肯定
    viewweiwu
        29
    viewweiwu  
    OP
       2022-03-01 21:01:49 +08:00
    @shanghai1998 感谢肯定
    viewweiwu
        30
    viewweiwu  
    OP
       2022-03-01 21:02:38 +08:00
    @aitaii Amiya 名字取自 《明日方舟》塔防游戏的角色
    viewweiwu
        31
    viewweiwu  
    OP
       2022-03-01 21:04:01 +08:00
    @2218675712 amis 有点面向不会技术的人使用了。Amiya 跟 Pro Components 走的路线一致,面向前端使用。
    viewweiwu
        32
    viewweiwu  
    OP
       2022-03-01 21:04:41 +08:00
    @lizhesystem 打工人就喜欢折腾
    pandaaa
        33
    pandaaa  
       2022-03-03 14:43:18 +08:00
    强啊楼主,给你大大的
    viewweiwu
        34
    viewweiwu  
    OP
       2022-03-03 14:46:07 +08:00
    @pandaaa 别摸鱼了,赶紧干活儿!
    pandaaa
        35
    pandaaa  
       2022-03-03 14:53:27 +08:00
    @viewweiwu 开周会,好不容易摸会
    rekulas
        36
    rekulas  
       2022-03-09 09:41:48 +08:00
    @viewweiwu 漫画模式阅读完成率高得多 参考 https://www.sohu.com/a/300039010_114877
    viewweiwu
        37
    viewweiwu  
    OP
       2022-03-09 13:42:37 +08:00
    @rekulas 这位博主我也关注了,确实挺有意思的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1997 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 45ms UTC 00:42 PVG 08:42 LAX 16:42 JFK 19:42
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86