阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 事件处理规范

事件处理规范

作者:陈川 阅读数:23288人阅读 分类: 前端综合

组件开发规范和事件处理规范是前端工程化的重要组成部分,合理的规范能够提升代码的可维护性和团队协作效率。下面从组件开发、事件处理两个方面展开详细说明。

组件开发规范

组件命名规范

组件命名采用大驼峰式(PascalCase),与文件名保持一致。多单词组合要避免缩写,保持语义完整。

// Good
UserProfileCard.jsx
OrderStatusBadge.jsx

// Bad
userProfile.jsx  // 不符合大驼峰
usrPrfCard.jsx   // 不推荐缩写

目录结构

组件相关文件统一放在components目录下,复杂组件建立独立文件夹:

src/
  components/
    Button/
      index.jsx
      style.module.css
      Button.test.js
    Form/
      Input/
        index.jsx
        InputItem.jsx

Props 类型定义

必须使用 TypeScript 或 PropTypes 明确定义 props 类型:

interface ButtonProps {
  size?: 'small' | 'medium' | 'large';
  variant?: 'primary' | 'secondary';
  disabled?: boolean;
  onClick?: (event: React.MouseEvent) => void;
}

const Button: React.FC<ButtonProps> = ({ 
  size = 'medium',
  variant = 'primary',
  ...props
}) => {
  /* ... */
}

样式管理

推荐 CSS Modules 或 styled-components:

// CSS Modules 示例
import styles from './Button.module.css';

const Button = () => (
  <button className={`${styles.btn} ${styles.primary}`}>
    Click
  </button>
);

// styled-components 示例
const StyledButton = styled.button`
  padding: ${props => props.size === 'large' ? '12px 24px' : '8px 16px'};
  background: ${props => props.theme.primary};
`;

事件处理规范

命名约定

事件处理函数以handle前缀开头,props 回调以on前缀开头:

const handleClick = (e) => {
  console.log('Button clicked', e.target);
};

<Button onClick={handleClick} />

// 组件内部暴露事件
function Modal({ onClose }) {
  const handleClose = () => {
    // 清理逻辑...
    onClose?.();
  };
}

事件对象处理

始终考虑事件代理和默认行为阻止:

// 列表项点击事件代理
function List({ items }) {
  const handleClick = (e) => {
    const itemId = e.target.dataset.id;
    if (itemId) {
      // 处理具体项点击
    }
  };

  return (
    <ul onClick={handleClick}>
      {items.map(item => (
        <li key={item.id} data-id={item.id}>{item.text}</li>
      ))}
    </ul>
  );
}

// 表单提交
const handleSubmit = (e) => {
  e.preventDefault();
  // 验证和处理数据
};

异步事件处理

需要处理加载状态和错误捕获:

function AsyncButton() {
  const [loading, setLoading] = useState(false);

  const handleClick = async () => {
    try {
      setLoading(true);
      await fetchData();
    } catch (error) {
      console.error('Fetch failed:', error);
    } finally {
      setLoading(false);
    }
  };

  return <button onClick={handleClick} disabled={loading} />;
}

自定义事件

复杂组件需要定义详细的事件契约:

// 类型定义
type CalendarEvent = {
  date: Date;
  type: 'select' | 'hover';
  nativeEvent: React.MouseEvent;
};

interface CalendarProps {
  onDateChange?: (event: CalendarEvent) => void;
}

// 事件触发
const emitDateChange = (date: Date, type: CalendarEvent['type'], e: React.MouseEvent) => {
  onDateChange?.({
    date,
    type,
    nativeEvent: e
  });
};

性能优化

事件节流与防抖

高频事件需要做性能优化:

import { throttle, debounce } from 'lodash-es';

// 滚动事件节流
const handleScroll = throttle((e) => {
  console.log('Scrolling', e.target.scrollTop);
}, 200);

// 搜索框防抖
const handleSearch = debounce((keyword) => {
  searchAPI(keyword);
}, 500);

事件监听清理

组件卸载时必须移除全局事件监听:

useEffect(() => {
  const handleKeyDown = (e) => {
    if (e.key === 'Escape') handleClose();
  };

  window.addEventListener('keydown', handleKeyDown);
  return () => {
    window.removeEventListener('keydown', handleKeyDown);
  };
}, []);

可访问性规范

键盘事件

必须支持键盘操作:

<div 
  role="button"
  tabIndex={0}
  onClick={handleClick}
  onKeyDown={(e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      handleClick();
    }
  }}
>
  可点击元素
</div>

ARIA 属性

复杂组件需要添加 ARIA 属性:

<div
  role="dialog"
  aria-labelledby="dialog-title"
  aria-modal="true"
>
  <h2 id="dialog-title">提示</h2>
  {/* 对话框内容 */}
</div>

测试规范

事件测试用例

使用 Testing Library 编写事件测试:

import { render, fireEvent } from '@testing-library/react';

test('should trigger onClick', () => {
  const handleClick = jest.fn();
  const { getByText } = render(<Button onClick={handleClick} />);
  
  fireEvent.click(getByText('Submit'));
  expect(handleClick).toHaveBeenCalledTimes(1);
});

// 模拟键盘事件
test('should handle keyboard event', () => {
  const { getByRole } = render(<SearchBox />);
  const input = getByRole('searchbox');
  
  fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
  // 验证搜索逻辑
});

文档规范

组件文档

使用 Storybook 或 JSDoc 记录组件事件:

/**
 * 通用按钮组件
 * 
 * @param {Object} props - 组件属性
 * @param {'small'|'medium'|'large'} [props.size=medium] - 按钮尺寸
 * @param {Function} props.onClick - 点击事件回调
 */
export function Button({ size = 'medium', onClick }) {
  // ...
}

事件流程图

复杂交互建议绘制事件流程图:

用户点击 → 触发handleClick → 验证数据 → 调用onSubmit → 发起API请求
          ↑               ↓
          错误反馈 ← 请求失败

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:状态管理规范

下一篇:样式隔离方案

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌