最近做开源的一些思考和收获

前言

最近给 varlet 组件库的 checkbox group 组件添加了一些新的feature,如optionslabel-keyvalue-key,这里记录下我的思考和收获。

支持 options

支持 options 的缘由

这个最开始考虑支持是因为这个 issue

耗子哥 商量了下,准备开始先支持 options,再去做这个组件

支持 options 的好处

简化代码结构

不用手动重复定义每个复选框的代码,只需在 options 属性中简单地传递复选框列表

动态生成

通过编程方式可以方便地动态生成或变更复选框选项,例如从后端获取数据后直接设置成 options

统一管理和配置

所有选项可以集中在一个数据结构中维护,方便在整个组件中统一对复选框选项数据的管理和使用,比如开关选项排布,值有所变更等均可写入该结构的逻辑内。

实现考量

label

这个字段在设计的时候,考虑支持三种类型,分别是 stringVNodeFunction,如下

ts 复制代码
export type CheckboxGroupOptionLabelRender = (option: CheckboxGroupOption, checked: boolean) => VNodeChild

export interface CheckboxGroupOption {
  label?: string | VNode | CheckboxGroupOptionLabelRender
  value?: any
  disabled?: boolean

  [key: PropertyKey]: any
}

最开始,我写这块内容的时候,考虑支持的是 label 插槽,类似于

后面和耗子哥交流了下,找到了另外一个思路,目前收集组件这种实现方式就很类似于插槽,开发者如果想使用 VNode 的话是行不通的,比如我想拿 h 函数来展示标签,模板是不支持的,就确定要支持VNode,考虑借助 tsx 的能力来实现。

支持 label-key 和 value-key

为什么要支持 label-key 和 value-key

为什么要支持 label-keyvalue-key 呢?这个我思考了下,感觉有以下几个方面

通用性与配置性

label-key 允许指定数据源中哪个属性应该显示给用户。数据源(通常是一个数据对象数组)上的属性名字可以不固定,通过配置 label-key,组件变得更加通用和可重用。例如,不同的应用场景可能有不同的数据接口

js 复制代码
const options1 = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; 

const options2 = [ 
  { id: 'a', transportation: 'Car' }, 
  { id: 'b', transportation: 'Bike' } 
 ]; 
html 复制代码
<CheckboxGroup options={options1} labelKey="name" /> 

<CheckboxGroup options={options2} labelKey="transportation" /> 

国际化

在国际化或者多语言支持的场景下,不同语言可能会有不同的展示文案。label-key 可以灵活地允许开发者动态更改显示语言

js 复制代码
const options = [ 
  { id: 1, enName: 'Apple', esName: 'Manzana' }, 
  { id: 2, enName: 'Orange', esName: 'Naranja' } 
]; 
html 复制代码
<CheckboxGroup options={options} labelKey={isSpanish ? 'esName' : 'enName'} />

自定义渲染

在某些复杂场景下,数据展示不一定是单一属性。例如

js 复制代码
const options = [ 
  { id: 1, firstName: 'Alice', lastName: 'Smith' }, 
  { id: 2, firstName: 'Bob', lastName: 'Johnson' } 
];
html 复制代码
<CheckboxGroup 
  options={options} 
  labelKey={(option) => `${option.firstName} ${option.lastName}`} 
/> 

代码

jsx 复制代码
import { defineComponent, type PropType } from 'vue'
import { isFunction } from '@varlet/shared'
import { CheckboxGroupOption } from './props'
import { createNamespace } from '../utils/components'
import Checkbox from '../checkbox'

const { name } = createNamespace('checkbox-group-option')

export default defineComponent({
  name,
  props: {
    labelKey: {
      type: String,
      required: true,
    },
    valueKey: {
      type: String,
      required: true,
    },
    option: {
      type: Object as PropType<CheckboxGroupOption>,
      required: true,
    },
  },
  setup(props) {
    return () => {
      const { option, labelKey, valueKey } = props

      return (
        <Checkbox checkedValue={option[valueKey]} disabled={option.disabled}>
          {{
            default: ({ checked }: { checked: boolean }) =>
              isFunction(option[labelKey]) ? option[labelKey](option, checked) : option[labelKey],
          }}
        </Checkbox>
      )
    }
  },
})

高内聚概念的实践

相信很多掘友都听说过 高内聚低耦合 这个软件工程的概念,我刚开始参加工作的时候,也知道这个概念,但是自己在真正的编码过程中,很少意识到自己可以主动践行这个概念。

前两天早上起床的时候,我打开微信,看到了耗子哥给我的留言,

一下子就想到了 高内聚 这个概念,对于 checkbox 组件,是否选中这个状态,是由它本身产生并控制的;而对于 checkbox group 组件,渲染出来的每一个 checkbox 组件,都能获取到组件是否被选中了。

但是,这里有两种思路去实现。

checkbox group 组件自己处理选中状态

checkbox group 组件这里加个判断,当前这个 optionvalue 是否在 modelValue 这个数组里面,对应我pr里面的code就是

checkbox 组件通过插槽暴露选中状态

checkbox 组件有几个插槽,如下图

其中,三个是 icon 相关的,肯定不合适,因为这三个插槽和选中状态没有深的关联,一般作为ui展示部分。

对于默认插槽,一般会渲染选项的标签,是比较适合来传递选中状态的,对应pr的code是

第二种选择就对应了 高内聚 概念,选中这个状态只有 checkbox 组件本身去控制,其他地方需要,可以通过插槽去接收,而第一种就显得代码会不凝练,假如我有需要去修改选中这块逻辑,那我两个地方都要改,而且要做出一样的改动,维护的成本就无形之中增加了。

结尾

以上就是我要分享的全部内容了,如有错误,欢迎指正~

相关推荐
永乐春秋28 分钟前
WEB攻防-通用漏洞&文件上传&js验证&mime&user.ini&语言特性
前端
鸽鸽程序猿29 分钟前
【前端】CSS
前端·css
ggdpzhk31 分钟前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
学不会•3 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
活宝小娜5 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点5 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow5 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o5 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic6 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā6 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue