做一个多标签Tab好难!(难点攻克)

145 阅读1分钟

书接上回,在做多标签时遇到遇到支线需要抉择,在确定一条明确的路径后,就要把道路扫清,攻克难点。

鼠标右键Tab时怎么出现菜单,并获取到当前点击的值

一开始设想的是给Tab加上onMenuContext事件,看了看antd的API,并没有这个事件。于是借助Dropdown,加入到每个tab中,使用renderTabBar,重新渲染Tab内容

const renderTabBar: TabsProps['renderTabBar'] = (
    tabBarProps,
    DefaultTabBar,
  ) => {

    return (
      <DefaultTabBar {...tabBarProps}>
        {(node) => {
          const currentTab = items.find((tab) => tab.key === node.key);
          const currentIndex = items.indexOf(currentTab);
          const menu: MenuProps['items'] = [
            {
              label: '关闭左侧',
              key: 'closeLeft',
              disabled: currentIndex === 0,
            },
            {
              label: '关闭右侧',
              key: 'closeRight',
              disabled: currentIndex === items.length - 1,
            },
            {
              label: '关闭其他',
              key: 'closeOthers',
              disabled: items.length === 1,
            },
            {
              label: '关闭全部',
              key: 'closeAll',
            },
          ];
          const handleMenuClick: MenuProps['onClick'] = ({ key }) => {
            // 实现关闭tab的功能,例如关闭当前tab
            console.log('Menu item clicked:', key);
            onContextMenuClick?.(node.key, key);
          };

          return (
            <DraggableTabNode
              key={node.key}
              index={node.key!}
              moveNode={moveTabNode}
            >
              <Dropdown
                menu={{ items: menu, onClick: handleMenuClick }}
                trigger={['contextMenu']}
              >
                {node}
              </Dropdown>
            </DraggableTabNode>
          );
        }}
      </DefaultTabBar>
    );
  };

受控与非受控

平时的Tab组件,我们有时候会传入activeKey,有时候则不传入。当不传入的时候为何也能生效呢。我猜想是当传入activeKey时是受控模式,当前激活值由传入的activeKey决定,当不传入时,则由另一个state决定。

const DraggableTabs: React.FC<DragTabProps> = (props) => {
  const {
    items = [],
    enableRightClick = false,
    defaultRoute,
    onChange,
    onItemsChange,
    ...otherProps
  } = props;

  const [order, setOrder] = useState<React.Key[]>(
    items.map((item) => item.key),
  );
  const [currentActiveKey, setCurrentActiveKey] = useState(items?.[0]?.key);

  // 判断是否是受控状态
  const inControl = 'activeKey' in otherProps;

  const realActiveKey = inControl ? otherProps?.activeKey : currentActiveKey;
  ... 剩余代码
}