V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
revalue
V2EX  ›  Vue.js

为什么我反对在 ui 组件库之上,再作对 template 进行 for 循环遍历 json 的封装?

  •  2
     
  •   revalue · 2020-06-08 10:27:13 +08:00 · 4021 次点击
    这是一个创建于 1634 天前的主题,其中的信息可能已经有所发展或是发生改变。
    看到隔壁贴,/t/679490 ,这个老哥最终成品方向还不确定,我也不是针对这个老哥的模式。我把其一个可能的方向简化的话就类似于这个链接 https://www.cnblogs.com/wisewrong/p/9052467.html 。(代码超级简单)

    这个原理也很简单,就是在 vue template 上 for 遍历这个 json,通过 if else 得出最后的 vue dom,就是这样封装。其实这个循环加封装就损失掉了 template 的可拓展性,应对复杂的场景,你必须用 hack 的方式设立并传个 slot 进去这个组件把损失掉的 template 拓展性给补回来。然后你这种 hack 又要加字段说明。像这样,每个人往上面补一刀,之后这个模块基本上就废了。

    除非你这个 json 设计,可迁移和可拓展性很强,比如你 json 还有别的用途,能拓展出新的配套功能配套设施。否则我觉得这是“脱裤子放屁”,这种封装只是把数据换了一种形式来表达,从 html 转为同等的 json,代码量几乎没减少,只能说在个别人看来,js object 比一大段 html 代码要美观一点。我组里已经有很多同学做成这个样子作为封装来邀功,“百花齐放”,封装后调用接口不一,我觉得用起来太难受了。

    我不是说反对 json Schema 。而是反对根据 json Schema 来在 template 上 for 循环遍历然后 if else 。其他的比如根据 json 代码生成 template 代码,我是比较看好的。

    PS:我想了下为什么封装那么难,以至于我更提倡代码生成器,是因为 vue 的 2.x 版本没有提供对 template 的“业务逻辑”的封装。受 react hooks 影响,在最近两年其他框架新版本开始有对业务逻辑的封装。而对比来看,像 vue 如果去封装“ui 组件库”,问题不是很大的。
    26 条回复    2020-06-09 19:44:40 +08:00
    revalue
        1
    revalue  
    OP
       2020-06-08 10:41:53 +08:00
    封装成组件为了减少这个组件内的“组件参数”和“组件配置”的重复填写?是一个层面,但是其减少的填写量远远不如对 echarts 这些组件的再次封装的效果。在这个封装问题里面,这种必要性不是很充分。
    TsubasaHanekaw
        2
    TsubasaHanekaw  
       2020-06-08 10:54:55 +08:00
    这种东西最终成品就是 用户可以通过拖控件方式 自定义表单
    codermagefox
        3
    codermagefox  
       2020-06-08 12:58:46 +08:00
    这种问题其实都是表面问题,归根到底就是:

    究竟要不要给用户掌握编程能力?如果给,给到什么级别?编程能力究竟应该给开发者还是用户?
    Qinmei
        4
    Qinmei  
       2020-06-08 13:19:02 +08:00
    我不是很赞同这种设计模式, 表单一般都是 UI 框架封装好的, 我们直接调用组件即可, 那对于前端来说, 直接写组件跟写 json 其实没差别, 但是加了一层之后, 我们不仅要知道 json 层的规则, 我们还要知道组件的规则, 有点多余了;

    我更倾向于只抽象逻辑, 但是前端这块其实很少有
    revalue
        5
    revalue  
    OP
       2020-06-08 13:23:11 +08:00
    @codermagefox 想到 dreamweaver 就知道这个选择题不好做了。现成的阿里开源出来的 Fusion 、飞冰这些,还是马马虎虎。
    SingeeKing
        6
    SingeeKing  
       2020-06-08 13:31:11 +08:00
    歪个楼,微信小程序只能这么干( html 组件自动转换基本就是废的),然后用起来真的就十分不爽
    no1xsyzy
        7
    no1xsyzy  
       2020-06-08 13:34:16 +08:00
    区分封装和代码生成器,说到底是因为没有 “宏”( AST 层面的宏)
    lisp 大家族欢迎你(误
    billLiao
        8
    billLiao  
       2020-06-08 13:44:48 +08:00 via Android
    @Qinmei #4
    forbreak
        9
    forbreak  
       2020-06-08 13:46:31 +08:00
    我现在也在这么干,最终是为了通过拖拉控件实现自定义表单。拖拉完成表单直接在线使用。如果生成 template,我不能直接使用,需要再次打包,重启才能用。 建的的表单拖拉一下很方便,就是复杂业务处理这块暂时还没有好的方式。
    redbuck
        10
    redbuck  
       2020-06-08 13:52:38 +08:00
    应用场景还是有的.
    比如一些弹窗查询之类的.

    可以在他的基础上再封装为函数.
    const result = await formAction({
    fields: [
    {type: ''},
    ...
    ]
    })

    比起封装为组件要灵活一些.
    ql9075
        11
    ql9075  
       2020-06-08 14:01:49 +08:00
    当你遇到大量重复页面,重复的 ui 你就会想到这些页面 不同的都是数据。为什么不抽象出来,让数据来控制页面的展示。你不用关心 css, html 的具体实现,如果你想快速配置页面只需了解 json 数据配置,如果你想做更复杂的应用,你可以修改底层逻辑更抽象的封装。
    jrtzxh020
        12
    jrtzxh020  
       2020-06-08 14:15:45 +08:00
    开发如 EPR 这种重复繁琐的 UI,还是很有必要的。
    dodo2012
        13
    dodo2012  
       2020-06-08 14:27:06 +08:00
    我现在做 vue 表单就是自己实现的拖拉生成,其实这东西,只要统一好接口方式,没那么麻烦的
    toesbieya
        14
    toesbieya  
       2020-06-08 14:34:55 +08:00
    写动态组件用 render 是最好的
    felixpy
        15
    felixpy  
       2020-06-09 00:57:52 +08:00
    隔壁楼主来了哈哈。老哥的关注点好像在 UI 框架的适配器上了,其实我感觉这个这个不是重点。复杂业务场景下大部分表单元素都是需要封装成一个支持 v-model 的自定义表单组件的,只有少部分的没啥逻辑的组件能用上适配器。如果业务的自定义组件需要用 hack 的方式插入 slot,那我觉得是这个自定义组件的抽象程度还不够。

    另外,我也同意你的观点,简单的页面完全没必要使用 JSON 配置的方式,自己在 template 组织即可。

    JSON 配置的方式其实是为了解决一类问题。假设我们有一个商品录入系统,总共需要录入 50 种类别的商品,每一类商品需要通过表单字段填写 30 条的信息。其中这些表单的特点如下:

    - 不同类别商品需要填写的表单字段 80% 可以进行复用,但是相同字段在每个类别下可能校验规则、可选择项、提示语等不同
    - 字段与字段之间具有一些相同的联动规则,比如不管在其中 20 个商品类别下,只有填写了字段 A 才能填写字段 B

    这种情况,我相信大家都不会写 50 个表单页,自己在每个表单页再去组织这些组件,同时处理各种不一样的地方。
    felixpy
        16
    felixpy  
       2020-06-09 01:00:40 +08:00
    @toesbieya 渲染函数很强大也很晦涩,可以考虑下 JSX 之类的
    felixpy
        17
    felixpy  
       2020-06-09 01:10:31 +08:00
    @forbreak 复杂业务的处理可以把封装到自定义组件里面,如果是通用的逻辑可以抽象到 composition-api 里面。另外如果一个组件在不同场景下有不同的业务逻辑,就可以考虑抽象成一个 组件选项 来控制。
    revalue
        18
    revalue  
    OP
       2020-06-09 09:30:48 +08:00
    @felixpy 啊不是,我觉得你没有理解我的意思,你太过客气了。

    我司就是已经跑过了 15 楼说的那个阶段,现在最大的问题是如 17 楼所说,所谓的“组件选项”太多了。

    “组件选项”只有 0 个或无数个,如果作为后来接手这些模块的人,你就能感受到压力了。
    revalue
        19
    revalue  
    OP
       2020-06-09 09:31:51 +08:00
    你这组件选项,控制的不是某 ui 组件,而是控制一个里面一堆 ui 组件的黑盒,我说这才是麻烦的地方
    wly19960911
        20
    wly19960911  
       2020-06-09 09:35:37 +08:00
    @revalue 那问题是 template 无法维护,你不用文档和需求固定下来,无限制的扩张扩展性根本是一个无法维护的怪物。今天这个人一个这样的需求,明天那个另外一个需求,我做这个的最大原因就是固定功能,几十个奇葩功能的表单,表单多达 30 多个字段,每次 template 都得写 1000 行,这种代码就好维护了?
    revalue
        21
    revalue  
    OP
       2020-06-09 09:46:26 +08:00
    首先“需求常变更调整”是另外一个问题,是侧面影响这个问题的因素。

    如果把 1000 行 template 用 json Schema 来描述,就会变好了吗?除非你把后端发过来的 json 直接拿来用。json Schema 来描述,你的 template 就要考虑是否循环遍历 json 然后渲染了,只是最多把一些默认的配置封进去而已,如果这些默认设置不满意,就需要加组件参数去改。我说的就是这种参数特别难维护。
    wly19960911
        22
    wly19960911  
       2020-06-09 09:55:39 +08:00
    @revalue 这种参数很难维护吗?无非就是根据计算属性来处理相关的多个参数合并操作,而且我用的数据结构类似 echarts 的 series,不同的 type 不同的选择项,加上完全的 typescript 注释和工厂类创建。维护业务组件的正常操作而已。不满意继续加新的 type,老的组件不动,开发新的组件来逐步替换老组件

    而且新的需求上来了,你也要去改老组件啊...这种遍历循环 json 的组件真的没什么难做的,难做的是那些带 if 逻辑的 json schema,我也没兴趣做,因为完全没必要,我这里效果太差了。
    taowen
        23
    taowen  
       2020-06-09 13:46:16 +08:00
    一个解决方案本身并没有对错和好坏,要看这个解决方案是解决什么问题的。我尝试列举三个问题:

    * jsx / tsx 等方案的编程反馈周期慢,一个界面的修改,从改源代码到看到效果需要好几秒钟(如果 webpack 等优化不好的话)。
    * 最终用户需要能够自定义自己的界面,比如店铺要装修,报表需要自定义的仪表盘。
    * CRUD 写得太烦躁了,每个都差不多。但是每个又有不同。

    从这三个问题出发,都有动机自己在现有的前端技术上架一层。

    * 拿 JSON/XML 等方式定义一个自己的模板语言,自己写一个解释器,然后支持拖拽。所见即所得的 GUI Designer,解决了反馈周期慢的问题。
    * 给用户一个店铺装修器,生成的描述文件存数据库。渲染的时候取出来,动态执行。
    * CRUD 就不用说了。解释器的方案就是动态代码生成。静态代码生成是另外一条路。仅仅是生成的话,静态动态区别不大。难点在于 20%不同的逻辑,怎么指定。静态的方案要比动态的方案更好做一些。

    每个不同的问题,对于最终这个方案好还是坏的定义都不同。每个问题都有自己细微的难点,比如 Gui Designer 怎么表达复杂的响应式排版,CRUD 怎么表达差异的逻辑部分等。做出一个 60 分的解决方案,可能带来的收益,还不足以支付切换解决方案带来的成本。
    xingyuc
        24
    xingyuc  
       2020-06-09 14:29:07 +08:00
    @jrtzxh020 上百个页面弹窗里面的输入框,cell……想想就可怕
    xingyuc
        25
    xingyuc  
       2020-06-09 14:35:55 +08:00
    @taowen 网易博客、QQ 空间的效果么
    wisetc
        26
    wisetc  
       2020-06-09 19:44:40 +08:00 via iPhone
    还是 json 大法好,这种我用过的,适合大表单,好处是利于测试,以及可以赋初值。看下面的定义就晓得了,属性超级多。

    ```ts
    enum Widget {
    div,
    radio,
    radioGroup,
    select,
    date
    }

    interface Option {
    label: string;
    value: string;
    }

    interface Field {
    label: string;
    hideLabel?: boolean;
    id: string;
    type: Function;
    hidden: boolean;
    labelAsSuffix?: boolean;
    defaultValue?: any;
    belongsTo?: string;
    widget?: Widget;
    required?: boolean;
    options?: Option[];
    fetchMethod?: () => Promise<any>;
    delayFetchMethod?: () => Promise<any>;
    suffixText?: String;
    postMethod?(val: any): any;
    fieldSet?: Field[];
    close?: boolean;
    rest?: object;
    }
    ```

    随手定义的分享出来,不过自己写的,别人未必能看懂。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3648 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 05:04 · PVG 13:04 · LAX 21:04 · JFK 00:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.