AntdUI和NextUI源码对比阅读(二)跟踪onChange

577 阅读2分钟

为什么要跟踪onChange?

因为源码庞杂同时依赖复杂。我们需要聚焦一个细小的点来顺藤摸瓜,才有可能有收获。要不然容易迷失在茫茫源码中。

那为什么是onChange?

因为onChange涉及对数据的处理,这个才是组件的核心逻辑。

如何跟踪onChange?

以NextUI为例我们分为这几步来跟踪:

  1. 我们先看NextUI组件文档,为了确认onChange是哪个组件的参数。image.png 如上图发现onChange事件在Checkbox Group上,而不是在checkbox上,这缩小了我们检索范围

  2. 打开Checkbox Group的源码,找到接收参数的地方,开始跟踪:

    const CheckboxGroup = React.forwardRef<HTMLDivElement, CheckboxGroupProps>(
      (
        {
          color,
          labelColor,
          disabled,
          size,
          label,
          children,
          readOnly,
          row,
          ...props //很可能onChange藏在这里
        },
        ref: React.Ref<HTMLDivElement | null>
      ) => {
    

    因为onChange是用户传入的参数,一定会传参传入。 这里没有,很可能在props里面藏着

    那我们鼠标悬浮在props上:

    image.png 果然在!

  3. 根据上一步开始跟踪 props。

    image.png 发现:props 先传给 useCheckboxGroupState 然后传给useCheckboxGroup

  4. 开始分析useCheckboxGroupStateuseCheckboxGroup

对onChange做了哪些加工?

根据上一小结,onChange通过props传给useCheckboxGroupStateuseCheckboxGroup 。所以这一节通过分析useCheckboxGroupStateuseCheckboxGroup 来找到对onChange做了哪些加工?

  1. 分析useCheckboxGroupState 的输入,输出。

    const state = useCheckboxGroupState({
      ...props,
      isDisabled: disabled,
      isReadOnly: readOnly
    });
    

    输入,基本都是用户传入的参数:

    {
      ...props,
      isDisabled: disabled,
      isReadOnly: readOnly
    }
    

    输出:返回value的同时,还返回很多关于value的增删改查的函数

    export interface CheckboxGroupState {
      /** Current selected values. */
      readonly value: readonly string[],
    
      /** Whether the checkbox group is disabled. */
      readonly isDisabled: boolean,
    
      /** Whether the checkbox group is read only. */
      readonly isReadOnly: boolean,
    
      /** Returns whether the given value is selected. */
      isSelected(value: string): boolean,
    
      /** Sets the selected values. */
      setValue(value: string[]): void,
    
      /** Adds a value to the set of selected values. */
      addValue(value: string): void,
    
      /** Removes a value from the set of selected values. */
      removeValue(value: string): void,
    
      /** Toggles a value in the set of selected values. */
      toggleValue(value: string): void
    }
    
  2. 分析useCheckboxGroup

    const { groupProps } = useCheckboxGroup(
      {
        ...props,
        'aria-label':
          props['aria-label'] ||
          (typeof label === 'string' ? label : undefined),
        isDisabled: disabled,
        isReadOnly: readOnly
      },
      state
    );
    

    输入,用户传入的参数,和value,以及value增删改查的函数:

    (
      {
        ...props,
        'aria-label':
          props['aria-label'] ||
          (typeof label === 'string' ? label : undefined),
        isDisabled: disabled,
        isReadOnly: readOnly
      },
      state
    )   
    

    输出:groupProps 也就是传给div的参数, 也传给子组件

      <StyledCheckboxGroup
        ref={domRef}
        size={size}
        {...mergeProps(props, groupProps)}
      >
      
      ···
                                  //这里将value,value相关的函数传给子组件
      <CheckboxContext.Provider value={providerValue}>
        {children}
      </CheckboxContext.Provider>
    
    
  3. 总结

image.png

收获

通过将value的onChange传入useCheckbox,得到value的增删改查函数: 这样有几个好处:

  1. 提供的增删该查函数,将简化checkbox里面的代码逻辑
  2. 简化checkbox代码逻辑的同时,增加代码可读性
  3. 将value的onChange函数变为value的增删改查函数的过程中,可以增加对异常情况的检查。能增加代码的鲁棒性