zoukankan      html  css  js  c++  java
  • 设计公共组件需要注意什么

    本文源于我们近期 抽取以及维护 ListFrame[参考中有介绍] 公共组件 的思考 。
    抽取一个公共组件,至少应当仔细考虑一下4点:

    1、公共组件不应该集成定制性强的功能,可以集成通用或较固定的功能,但应默认关闭那些不常用的功能

    只有极少数列表用到的功能就不要封装了,封装他们 增加了公共组件的代码量,但又没有很高的利用率。

    几乎所有的列表都可以用到,但不同种类的列表 表现不一样(如内容类别搜索,文章类型的类别,游戏类型的类别 完全不同),就是定制性很强的功能了。
    定制性很强的功能封装起来需要包含各种情况,逻辑较复杂,另外也使列表的逻辑分散,不利于维护。试想一下,下次再扩展一个类型,岂不是还要修改这个ListFrame !
    (公共组件不能保持稳定的,就是失败的)

    这有点小儿科了吧!
    实际上识别出哪些功能是通用的(应该封装的),哪些是常用的(应该默认开启的),不能光靠拍脑袋,使用公共组件的过程,不断修正总结 很重要。
    维护公共组件,你一定要有一颗开放的心态。组件好不好,由使用的情况说了算,敢于承认失败,才能不断改进。

    2、参数的配置要简单且灵活

    如果你想让你的组件功能强大,通过配置就能快速扩展,那么一定要避免将配置设计的过于复杂。
    配置复杂,无异于将写源码的工作量 转移到了写配置上,没有任何好处,反而让代码更难理解(额外的要先理解你的公共组件)。

    将配置设计的简单关键就是:用好默认值和类型重载

    构建列表框架,你必须要考虑分页:
    有些列表(如展示全部内容的列表)是没有分页
    分页有pageNo和pageSize属性,且初始值是可以设定的,ajax请求时携带的参数名最好也是可以配置的
    于是可能你的组件应该这样使用:

      <list-frame :showPager="{
    show:true, pageNo:{ name:'pageNo', initial:1 }, pageSize:{ name:'pageSize', initial:10 }}"
    ></list-frame>

    后台在设计接口时,通常参数名就是 pageNo 和 pageSize;前端使用场景中基本上初始的pageNo是1,pageSize为10。采用默认值,所有的配置都可以省略:

    <list-frame :showPager="{show:true}"></list-frame>
    <!-- 没有传入的字段,就使用默认值,而非空(做好空值适配很重要) -->

    为了更简单,再加上类型重载。完整设计代码如下:

    class PagerConfig{
        show?:boolean,
        pageNo?:{
            name?:string,
            initial?:string
        }
        pageSize?:{
            name?:string,
            initial?:string
        }
    }
    
    // 类型重载
        showPager:Boolean | PagerConfig
    
    // 默认值的定义与使用:
    const defaultPager = {
      show: true,
      pageNo: {
        name: 'pageNo',
        initial: 1
      },
      pageSize: {
        name: 'pageSize',
        initial: 10
      }
    };
    
    this.pagerConfig = Object.assign(
      {},
      defaultPager,
      typeof this.showPager === 'boolean' ? { show: this.showPager } : this.showPager
    );
    // this.pagerConfig 就是最终的配置了!

    那么使用时,就可以这样写了

    <list-frame :showPager="true"></list-frame>
    或:
    <list-frame show-pager ></list-frame>

    现在可以看到,一切变的非常简单,同时又保持了足够的灵活性!(灵活性是指,任然可以灵活的配置参数名称 和 初始值)

    3、相关的配置要集中

     将相关的配置集中在一起,更利于用户使用,可读性更强。

    ListFrame 封装了 批量删除 和 批量上下架 的功能。为什么要将这两个功能封装呢?因为:
    1、有很多业务无关逻辑值得我们去封装,如disable校验,删除和下架时要弹出输入框,要求用户输入删除原因或下架原因;
    2、通用性很强,几乎所有的列表都有删除功能,所有已发布列表都有上下架功能;
    3、不同列表除了对应的上下架接口,删除接口不同外,好像没有什么其他不同的。

    看看下方代码:

        <!-- 集中配置前: -->
        <list-frame
          :getPageFn="getPage"
          :itemsDelAble="true"
          :delFn="delFn"
          :shelfOperateAble="true"
          :offshelfFn="offshelfFn"
          :onshelfFn="onshelfFn"
        ></list-frame>

    如果开启批量删除 除了设置 itemsDelAble 为 true,还要提供 delFn 删除方法;
    如果开启批量上下架 除了设置 shelfOperateAble 为 true ,还需要提供 offshelfFn 和 onshelfFn 两个方法。

    既然提开启功能和供方法必须同时存在,为什么不把他们绑定在一起呢?我们将 itemsDelAble 和 shelfOperateAble 有bool类型变成了 object 类型,于是很容易实现了集中配置的目标。

    对比一下将配置集中前后的代码,是否后者更容易理解,更方便使用了呢?

        <!-- 集中配置后: -->
        <list-frame
          :getPageFn="getPage"
          :itemsDelAble="{delFn}"
          :shelfOperateAble="{offshelfFn,onshelfFn}"
        ></list-frame>

    4、避免出现职能交叉的配置

    我发现,这一点错误,即便是大型UI框架也会犯。我现在开发的项目所采用的UI框架,关于Button就存在这个问题。下面就用个api截图来说明:(就不发 链接,也不指明是哪个框架了)

    按钮的 type 大部分值都是表示主题颜色的,如default,primary,info等,但 text(文本按钮) 和 dashed(虚线框按钮)除外,我觉得这两个应该是属于shape(形状)的值。
    这样的 type 和 shape 职能交叉了。现在要实现一个文本按钮,有不同颜色 —— 竟然做不到了!

    我们在开发 ListFrame 也存在这样的错误,后面使用时发现后才改正的,这里就不说了,因为上面举的例子已经能很好的说明这个注意点了。
    总之设置配置项时,保持高内聚,低耦合的原则是不变的!

  • 相关阅读:
    14.6 将运算分组为事务
    Android 取得 ListView中每个Item项目的值
    【编程题目】n 个骰子的点数
    【编程题目】扑克牌的顺子
    【编程题目】颠倒栈☆
    【编程题目】输出 1 到最大的 N 位数
    【编程题目】寻找丑数
    【编程题目】在字符串中删除特定的字符
    【编程题目】复杂链表的复制☆
    【编程题目】找出数组中两个只出现一次的数字 ★★(自己没做出来)
  • 原文地址:https://www.cnblogs.com/zhwc-5w4/p/13329818.html
Copyright © 2011-2022 走看看