useAccessibilityMenu菜单Hook

Violet230 +0/-0 0 0 正常 2025-12-24T07:01:19 React Hooks · 可访问性

在现代React应用中,可访问性是不可忽视的重要环节。useAccessibilityMenu Hook旨在为开发者提供一套完整的菜单组件可访问性解决方案。

核心功能

该Hook实现了键盘导航、焦点管理、Aria属性设置等核心可访问性功能。通过useRefuseEffect的组合,我们能够精确控制菜单项的焦点流转。

import { useState, useEffect, useRef } from 'react';

const useAccessibilityMenu = (items) => {
  const [activeIndex, setActiveIndex] = useState(-1);
  const menuRef = useRef(null);
  
  // 键盘事件处理
  const handleKeyDown = (event) => {
    if (!menuRef.current) return;
    
    switch (event.key) {
      case 'ArrowDown':
        event.preventDefault();
        setActiveIndex(prev => (prev + 1) % items.length);
        break;
      case 'ArrowUp':
        event.preventDefault();
        setActiveIndex(prev => (prev - 1 + items.length) % items.length);
        break;
      case 'Home':
        event.preventDefault();
        setActiveIndex(0);
        break;
      case 'End':
        event.preventDefault();
        setActiveIndex(items.length - 1);
        break;
      case 'Escape':
        setActiveIndex(-1);
        break;
      default:
        break;
    }
  };
  
  // 焦点管理
  useEffect(() => {
    if (activeIndex >= 0 && menuRef.current) {
      const activeElement = menuRef.current.children[activeIndex];
      if (activeElement) {
        activeElement.focus();
      }
    }
  }, [activeIndex]);
  
  // 初始化事件监听
  useEffect(() => {
    const menuElement = menuRef.current;
    if (menuElement) {
      menuElement.addEventListener('keydown', handleKeyDown);
      return () => {
        menuElement.removeEventListener('keydown', handleKeyDown);
      };
    }
  }, [items.length]);
  
  return {
    menuRef,
    activeIndex,
    setActiveIndex,
    getMenuItemProps: (index) => ({
      tabIndex: index === activeIndex ? 0 : -1,
      'aria-current': index === activeIndex ? 'true' : undefined
    })
  };
};

使用示例

const MenuComponent = () => {
  const menuItems = ['首页', '产品', '关于我们', '联系我们'];
  const { menuRef, activeIndex, getMenuItemProps } = useAccessibilityMenu(menuItems);
  
  return (
    <nav ref={menuRef} role="menubar">
      {menuItems.map((item, index) => (
        <button
          key={index}
          {...getMenuItemProps(index)}
          onClick={() => console.log('点击:', item)}
        >
          {item}
        </button>
      ))}
    </nav>
  );
};

性能优化

通过useCallback缓存事件处理器,避免不必要的重新渲染。同时使用useRef存储DOM引用,确保事件监听器的正确绑定与解绑。该Hook设计遵循React Hooks最佳实践,可有效提升菜单组件的可访问性与用户体验。

推广
广告位招租

讨论

0/2000