SuperAPI AI 工具集

coupling

前端与建站

查看项目

更新于 10-16 04:43

技能介绍

用途

本技能用于处理前端代码中的耦合问题,核心目标是“最小化代码变更的影响范围”:一次功能改动不应破坏其他功能。当出现以下信号时适用:props 需要穿过 3 层以上组件层级;一个 Hook 返回 5 个以上值;修改 A 时导致无关的 B 出错。

主要能力

资料给出的核心模式与改进方法如下:

  1. 消除 Props Drilling(组合模式)

问题写法:props 逐层向下传递。

function ItemEditModal({ items, onConfirm, onClose }) {
  return (
    <Modal onClose={onClose}>
      <ItemEditBody items={items} onConfirm={onConfirm} onClose={onClose} />
    </Modal>
  );
}
function ItemEditBody({ items, onConfirm, onClose }) {
  return (
    <>
      <Button onClick={onClose}>닫기</Button>
      <ItemEditList items={items} onConfirm={onConfirm} />
    </>
  );
}

改进写法:用 children 进行组合。

function ItemEditModal({ items, onConfirm, onClose }) {
  return (
    <Modal onClose={onClose}>
      <ItemEditBody onClose={onClose}>
        <ItemEditList items={items} onConfirm={onConfirm} />
      </ItemEditBody>
    </Modal>
  );
}
function ItemEditBody({ children, onClose }) {
  return <><Button onClick={onClose}>닫기</Button>{children}</>;
}
  1. 职责分离

问题写法:一个 Hook 管理所有状态。

function usePageState() {
  const [query] = useQueryParams({
    cardId: NumberParam, dateFrom: DateParam, dateTo: DateParam, statusList: ArrayParam
  });
}

改进写法:拆分为单一职责 Hook。

function useCardIdQueryParam() {
  const [cardId, setCardId] = useQueryParam("cardId", NumberParam);
  return [cardId ?? undefined, setCardId] as const;
}

快速参考

资料提供的“代码坏味道 → 改进方法”对照:

  • 穿过 3 层以上层级的 props → 组合模式:使用 children
  • 返回 5 个以上值的 Hook → 拆分为单一职责 Hook
  • 修改 A 时无关的 B 出错 → 识别耦合点后引入接口
  • 被所有地方 import 的 util → 移动到使用处附近

适用场景

  • 组件层级较深、props 层层透传的界面结构。
  • Hook 承担过多职责、返回值过多的情况。
  • 修改一处代码牵连多处、影响范围难以预估的代码库。
  • 公共 util 被广泛引用、改动成本高的项目。

限制与注意事项

  • Context 的适用条件:仅用于真正的全局关注点,例如主题、语言区域(locale)、认证状态,或需要被 10 个以上组件使用的数据。不要为了回避组合模式而滥用 Context。
  • 例外:有些情况下重复反而更好——当各页面行为存在差异的可能时;当修改公共代码会导致所有依赖代码的测试负担过大时。

参考

https://frontend-fundamentals.com/code-quality/loosely-coupled/