从实战出发-前端常规组件设计思路

写此篇原因

前端组件设计思路或原则的,此类文章网上已很多,有些陈词滥调了。但此类文章大部分都是直接写结果而忽略了原因,导致阅读难度较大。本人希望从解决问题的角度出发,写这篇组件设计。如果觉得有点作用,希望大家帮忙点一下赞。

为什么要写组件?

此问题没有固定的答案,大家要根据自身情况来思考。我在当前项目,写公共组件原因是:核心是为了提高团队效率,其次是统一ui风格。

因为当前项目是管理后台项目,只有4,5个前端,且进入了中期。若是前期,写组件核心或许会放在维护性和统一ui风格上,使项目可以更稳定,组件也更容易迭代。但现在是中期,且前端人数不算多。重心放在提升团队效率上即可。

该怎么写公共组件?

根据我自身项目的情况,重心放在提升团队效率即可。那我要解决的问题有:

  • 易上手,易阅读,一接触就能使用其核心功能,其余功能也能快速上手使用。
  • 中高度封装,尽量减少使用者的代码量。
  • 通用性强,能满足常见的业务功能

解决以上问题,那么我会得到一个高效率的公共组件。目前基础的增删改查的表格页面,三个组件即可搞定。

从实战出发-前端常规组件设计思路

由于团队特殊情况,很多小伙伴不太愿意使用公共组件。易上手易阅读这个是我首要解决的问题。大家根据自身当前情况,来思考自己要解决什么问题。我给自己定的标准是:小组件,使用者一看就能直接使用。大组件,2分钟内就能直接上手使用。

🐯 易上手易阅读问题

解决这个问题,得思考使用者是怎么样使用组件的。第一,使用者如何查询到此组件。由于我们团队没有组件库,要使用某个组件,小伙伴会有两个途径去查询这个组件。1、看到之前在使用此组件的代码。2、直接看组件代码。第二,使用者,在使用组件中,如果遇到特殊的业务功能,他如何在组件中找到合适的api去解决此问题。

1.文档

由于团队无组件库文档,文档只能写在代码上。除了有此组件和api的说明,特定增加了一个快速复制粘贴功能。确保使用者看到此组件,马上就能使用此组件的核心功能。

从实战出发-前端常规组件设计思路

2.单一职责

这个就是老生常谈的组件思路了。举个例子说明一下:我写了个页面表格组件。后面小伙伴说我这组件能否api加个选项,可以选择是否需要分页器。

我回答肯定是:NO。因为我这页面表格组件,它的职责就是:表格和分页器的连接器。如果你要单表格,不要分页器,那么你就用基础表格组件,而不是页面表格组件。如果在这个组件加了是否需要分页器的选项,把不该是它的事放到了它身上,看起来它的功能多了,但其实混淆了它的职责,影响阅读性。

  • 组件源码

<template>
   // 基础表格组件
  <BaseTable
    :data="props.data"
    v-bind="$attrs"
    :columns="columnsHandle"
    :handleList="handleList"
    @selection-change="selectionChange"
  >
    <template v-for="item in slotList" :key="item" #[item]="scope">
      <slot :name="item" v-bind="scope"></slot>
    </template>
  </BaseTable>
    // 分页器
  <Pagination
    v-model:page="pageNum"
    v-model:limit="pageSize"
    @pagination="paginationFnc"
    :total="total"
  />
</template>

3.主次之分(单一职责的补充)

阅读性最高的组件,就是只有一个主要api,只要有这个api有参数这个组件就能运行,其他的api只是起辅助作用。这个是我自己悟的,仅供大家参考哈。举个例子:

// elementplaus的input组件
 <el-input v-model="input" style="width: 240px" placeholder="Please input" />

这个组件核心api就是v-model,只要这个api有值,就完成了此组件80%的功能。其他的api仅起辅助作用。大家可以留意一下,elementplaus组件,基本都是如此。现在vue3主版本支撑defineModel,v-model使用更加容易了,善用多用v-model,会让你的组件可阅读性上一个档次。

但很多时候,组件需要两个api才能运行起来,有两个主要api,其实也行。比如我写的基础表格组件,需要date和columns两个属性才能跑起来。这种阅读性会差一点,但也还行。但主要api不能超过3,一个组件要3个主要api才能运行起来,那这个组件使用起来,肯定是苛刻,阅读性也差。

<template>
  <BaseTable :data="data" :columns="columns">
  </BaseTable>
 </template> 
 <script lang="ts" setup>
  const data = ref([
    {
      data1: 1,
      data2: 2,
    }])
  const columns = ref([
  { label: 'data1表格头', prop: 'data1', showOverflowTooltip: true }
  ])
</script>

4.扁平化的state和props

给组件传递props时,建议用更扁平化的props,而不要用嵌套的对象或数组。这个懂得都懂。
特殊情况,需要传对象,比如我做的搜索栏组件,其中有一个参数itemProps传入的就是对象。但这个api职责其实也是单一,比如搜索框是input框,如果要修改这个input框,那就在itemProps传入ElInput的api即可。

这条原则,核心是每个api职责必须是单一的,别整混合api。

API columns = {
      type:'input' | 'select' | 'datePicker'
      itemProps:{} //element组件的内容,完美继承
      label:搜索标题
      key:搜索key
    }

5.单向数据流

这个是vue或react任何框架的常规操作了,组件也应追寻此原则。之前有小伙伴就是父级将一整对象传到子组件里面,然后子组件直接对该对象进行操作,子组件直接操作父组件数据,数据逆流向,后期维护阅读性极差。看完他的组件,我马上就重构了。

6.添加ts类型

ts类型提示能大大减轻组件的使用难度,这是不容质疑的。react是个js库,天生有ts支持。vue虽然一直在加强对ts的支持,但还是有不少问题。这个只能尽量写。但如果是通过数据去驱动的中大型组件,那必须写组件的ts支持,能大大减轻使用者负担。
举个例子:

import { ElSelect } from 'element-plus'
type ElSelectPropsValue = InstanceType<typeof ElSelect>['$props']
export type Column =
  | ({
      type: 'select'
      itemProps?: ElSelectPropsValue
      optionList: optionListValue
    })

上面是我组件api的一个ts类型。我在itemProps直接加上了ElSelect的ts类型。那么使用者在使用此api调整select框的时候,就会有ts的提示。能大大提升效率。

从实战出发-前端常规组件设计思路

总结:

现在我们模拟使用一下目前的公共组件。遇到有一个要使用的组件,直接复制示例到使用的地方即可。这个公共组件职责是单一的,主要依靠一个api即可运行起来。一下子就能知道这个组件的用法了。如果需要适配,ts有语法支持。这个组件实在是太好用了。

以上当然是我臆想,现实中才没那么顺利(ಥ﹏ಥ)。但这一套组合拳下来,组件的可阅读性和上手难度,应该得到了大大的改善。大家如果有更好的组件设计思路,欢迎补充。

🐯通用性问题

如果一个组件易读易上手,往往这个代码通用性也是很强的。不过还有些得补充一下,先在这里挖一下坑,过几天再补上(如果公司不突然加活的话)。欢迎大佬指出问题和提供建议,感谢。如果觉得这篇文章有点用,帮忙点一下赞哈。

Tip 如何解决问题?三步走

1.发现问题。2.解决问题。3.监控问题

举个大家习以为常的例子,发现了某个模块在很多地方都要使用,写个组件封装一下,把ui和常用参数配置好,让大家只关注业务即可。上面两步就是发现问题和解决问题。

但很多人忽略了第三步,第三步其实是必需的。把组件搞完后,拿一段时间去看看小伙伴使用的情况。收集意见和修改。能让组件更丝滑,也能大大提升其他小伙伴使用组件的意愿。

原文链接:https://juejin.cn/post/7355285469640998939 作者:夏目友人爱吃豆腐

(0)
上一篇 2024年4月9日 上午10:28
下一篇 2024年4月9日 上午10:39

相关推荐

发表回复

登录后才能评论