普通视图

发现新文章,点击刷新页面。
昨天 — 2025年6月29日首页

无障碍功能是必须的

2025年6月29日 19:31

为什么无障碍设施如此重要

无障碍设计是一项基本职责,而非次要考虑因素。每个人都应该能够使用您的应用,包括那些行动不便的人。包容性设计确保了用户能够平等地使用您的产品,无论他们是否有视力障碍、行动障碍或认知障碍。

在许多国家,无障碍设施也是一项法律要求(例如美国的 ADA、欧洲的 EN 301 549)。

a11y React 开发者最佳实践

1. 使用语义HTML

  • 偏好本土元素
  • 避免使用 div 进行交互式 UI — 屏幕阅读器会跳过它们

2. 确保键盘导航性

  • 每个交互元素都应该可以通过 Tab 和 Enter 访问和操作
  • 慎重使用 tabindex (避免 tabindex="0" 过载)

3. 需要时添加 ARIA 属性

  • 使用 aria-label、aria-hidden、aria-live 为屏幕阅读器提供上下文
  • 但是当语义 HTML 可以完成工作时,不要过度使用 ARIA

4. 为图片提供替代文本

  • 对重要图片使用有意义的 alt=""
  • 使用 alt="" 来隐藏装饰性的

5. 颜色对比度和焦点指示器

  • 确保文本具有高对比度(根据 WCAG AA/AAA 检查)
  • 不要删除焦点轮廓——如果需要,可以自定义它们

6. 表单错误处理

  • 使用 aria-scribeby 链接表单错误
  • 在模糊或提交时进行验证,而不仅仅是在更改时

确保年度合规性的工具

  • axe DevTools(Chrome 扩展程序)——实时分析 WCAG 违规行为
  • eslint-plugin-jsx-a11y — 查找缺失的角色、替代文本、标签陷阱
  • Lighthouse (Chrome/CI) — 审核中的 a11y 评分
  • 屏幕阅读器:NVDA(Windows)、VoiceOver(macOS)、ChromeVox

现实世界的可访问性审计技巧

  • 仅使用键盘即可导航整个应用程序
  • 使用屏幕阅读器浏览常见流程
  • 使用 contrast-ratio.com 等工具测试颜色对比度
  • 避免可能引发运动障碍的动画(尊重prefers-reduced-motion

编写可测试的无障碍代码

  • 使用自动化测试框架(如 Jest + Testing Library)确保交互元素的可访问性
  • 示例:getByRole('button', { name: /提交/i }) 能验证按钮是否具备正确语义
  • 利用 axe-core 集成到测试流程中,防止无障碍回归

组件库与设计系统中的无障碍策略

  • 选择已通过 WCAG 检测的组件库(如 Reach UI、Radix UI)
  • 在设计阶段加入辅助功能审核,比如组件状态下的焦点样式、键盘操作流
  • 定义通用的 a11y 设计 token,例如:焦点边框、aria 属性规范、alt 文案策略

团队协作与文化建设

  • 将无障碍视为团队代码评审中的一部分,而不是事后补救
  • 对设计师、开发者、测试人员进行基础的无障碍培训
  • 分享无障碍提升成果(如 Lighthouse 分数、用户正反馈),增强团队使命感

最终要点:以人为本,确保代码面向未来

Web 应该属于所有人
作为开发者,我们的代码承载着一种责任——让技术成为助力,而非障碍。

从一个有意义的 alt 文案,到为按钮保留焦点样式,哪怕是一个小小的调整,也可能极大改善一位用户的体验。

别等需求单提出来才去优化无障碍。把 a11y 当作质量保障的一部分,你做出的产品会更稳定、更持久,也更被信任。

每个开发人员都应该遵循的 10 个 React 最佳实践

2025年6月29日 11:14

前言

如今,前端开发的行业领导者仍然是 React。它强大的抽象、活跃的社区和丰富的生态系统,让开发者能够创建从企业级程序到业余项目的各种应用。

然而,强大的功能也伴随着诸多的复杂性。如果你忽视了久经考验的最佳实践,React 应用很容易变得难以管理、不一致或难以维护。

为了在 2025 年创建可扩展、稳定、有效且干净的 React 应用程序,每个认真的开发人员都应该遵循这十条 React 最佳实践。

1. 构建小型、专注且可重用的组件

为什么重要:

React 是基于组件的。你的用户界面本质上是由可复用的小部件组成的树状结构。但只有当这些元素职责单一且高度集中时,它才能成功。

避免使用臃肿的“上帝组件”,将 UI、逻辑和副作用都放在一个文件中处理。

你应该做什么:

  • 一个组件=一个目的
  • 将大组件分解成较小的组件
  • 在整个应用程序中重复使用组件以避免重复

例子

完成所有的事情,将其分解为:

<DashboardHeader />
<DashboardStats />
<DashboardActivity />

而不是

<Dashboard />

✅好处:

  • 更易于调试和测试
  • 鼓励重复使用
  • 保持文件简短易读

2. 使用带有 Hooks 的函数组件(优于类组件)

演变:

在 React 16.8 之前,类组件很常见。然而,目前,带有 hooks 的函数式组件被认为是最好的。

好处:

  • 更清晰的语法
  • 无需此绑定
  • Hooks 使状态和生命周期管理模块化且可重用

需要掌握的常见钩子:

| Hook                      | Purpose                                             |
|---------------------------|-----------------------------------------------------|
| `useState`                | Local state                                         |
| `useEffect`              | Side effects (API calls, subscriptions)             |
| `useRef`                 | Persisting mutable values without re-renders        |
| `useContext`             | Access global data without prop drilling            |
| `useReducer`             | More complex state logic (Redux-like)               |
| `useCallback`, `useMemo` | Performance optimization                            |
| **Custom Hooks**         | Abstract logic into reusable pieces                 |

3. 慎重提升状态(避免重复 Prop)

什么是提升状态?

当两个或多个组件需要访问相同状态时,应该解除最近的共同祖先。

需要避免的事情:

道具钻孔是通过几个不必要的中间组件插入道具的过程。

帮助工具:

  • React Context 用于轻量级共享状态
  • Zustand、Jotai 或 Redux Toolkit 适用于跨多个组件的复杂状态。

使用:

<UserContext.Provider value={user}>
  <App />
</UserContext.Provider>
而不是:
<App user={user}>
  <Sidebar user={user}>
    <Profile user={user} />
  </Sidebar>
</App>

4. 拥抱类型安全:TypeScript

为什么类型检查至关重要:

这种 JavaScript 是动态的。随着应用的增长,这种适应性可能会变成一个缺点。TypeScript(或 PropTypes)提供了一层保护。

TypeScript 的优点:

  • 在运行之前捕获错误
  • 强制一致的接口
  • 通过自动完成和内联文档改善开发人员体验

TypeScript 示例:

type User = {
  id: number;
  name: string;
  email: string;
};

function UserCard({ user }: { user: User }) {
  return <div>{user.name}</div>;
}

仅将 PropTypes 用于简单的应用程序。对于任何实际应用,请使用 TypeScript。

5.创建可扩展的文件/文件夹结构

为什么结构很重要:

杂乱的结构变得难以控制。可扩展的设计实现了无缝入职,并促进了合作。

流行图案:

  • 基于特征的结构
  • 领域驱动结构
  • 原子设计结构(原子、分子、生物体等)

建议设置:

src/
├── components/         # Reusable UI components
├── features/           # Feature-specific modules
│   └── auth/
│   └── dashboard/
├── hooks/              # Custom hooks
├── contexts/           # Context providers
├── pages/              # Route-level pages (Next.js)
├── utils/              # Helper functions
├── assets/             # Images, fonts, etc.

在主要文件夹中保留 README.md 来解释其结构。

6. 优化渲染:记忆重要内容

为什么要优化?

当组件的 props 或 state 发生变化时,React 会重新渲染它们。对于大型组件树来说,这可能会很昂贵。

记忆工具:

  • React.memo()– 跳过纯函数组件的重新渲染
  • useMemo()– 缓存昂贵的计算
  • useCallback()– 记忆回调函数以防止子进程重新渲染

专业提示:

不要盲目优化。使用React Profiler来识别瓶颈。

7. 编写可重用的自定义钩子

为什么要使用自定义钩子?

钩子是可重复使用的逻辑容器。如果您需要在多个组件之间重复逻辑,请使用自定义钩子。

例子:

function useFetch(url) {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetch(url).then(res => res.json()).then(setData);
  }, [url]);
  return data;
}

用法如下:

const userData = useFetch('/api/user');

最佳实践:

前缀为use
保持钩子纯粹且可组合
放置在hooks/ 文件夹内

8. 实现错误边界和回退 UI

React 并非万无一失

某个部分未解决的问题可能会导致用户界面崩溃。React 错误边界通过捕获错误提供温和的回退。

例子:

class ErrorBoundary extends React.Component {
  state = { hasError: false };
  static getDerivedStateFromError() {
    return { hasError: true };
  }
  render() {
    if (this.state.hasError) return <h1>Something went wrong.</h1>;
    return this.props.children;
  }
}

还可以使用:

  • Suspense延迟加载
  • 异步函数中的 Try/catch
  • 外部库如react-error-boundary

9. 测试组件:关注行为,而不是实现

为什么测试在 React 应用中很重要

测试的目标是建立对应用的信任,而不仅仅是发现缺陷。在现代 React 应用程序中进行测试可以确保您的用户界面 (UI) 在各种设备、状态和用户交互下都能正常运行。随着项目的进展,它可以保留您的逻辑,提供基于代码的文档,并避免回归。

思维转变: 将测试视为安全网,而不是琐事。它们让你能够大胆地重构,确保核心逻辑仍然有效。

您应该了解的测试类型

| Test Type      | Purpose                                           | Tools to Use                                 |
|----------------|---------------------------------------------------|----------------------------------------------|
| Unit Tests     | Test isolated components and logic                | Jest, React Testing Library                  |
| Integration    | Test how components work together                 | React Testing Library, Vitest                |
| E2E Tests      | Test full app behavior as a user would            | Cypress, Playwright, TestCafe                |
| Snapshot       | Detect unintended UI changes (with caution)       | Jest (with snapshot plugin)                  |

推荐的工具和生态系统

  • React 测试库 (RTL):使用用户交互测试您的应用程序,重点关注事件、可访问性角色和 DOM。
  • Jest:一个经过实战检验的 JavaScript 测试框架,具有内置的模拟、断言和快照。
  • Cypress 或 Playwright:在真实的浏览器设置中进行彻底的端到端 (E2E) 测试。真正实现用户流程的自动化。
  • MSW(模拟服务工作者):测试可以模拟 API 答案而不需要后端。

React 测试的最佳实践

1. 为用户行为编写测试,而不是内部实现
  • 错误:检查内部状态或类名
  • 好:点击按钮并检查结果是否显示
2. 使用getByRole, getByLabelText,getByText结束getByTestId
  • 这确保您的应用程序可访问且可测试
3.测试边缘情况:
  • 空状态
  • API 响应缓慢
  • 无效输入
  • 移动视口尺寸(E2E)
4.保持测试快速且确定——通过模拟 API 并在需要时使用伪计时器来避免不稳定的测试

示例测试用例(React 测试库)

jsx
复制编辑

test("increments counter on click", () => {
  render(<Counter />);
  const button = screen.getByRole("button", { name: /count/i });
  fireEvent.click(button);
  expect(button).toHaveTextContent("1");
});

黄金法则:

  • 测试用户关心的内容——行为、可访问性、交互。
  • 避免测试组件内部——结构、状态变量或 DOM 树形状。

想要在所有平台上打造高性能应用?

10. 无障碍功能(a11y)是必须的,而不是可能的

为什么无障碍设施如此重要

无障碍设计是一项基本职责,而非次要考虑因素。每个人都应该能够使用您的应用,包括那些行动不便的人。包容性设计确保了用户能够平等地使用您的产品,无论他们是否有视力障碍、行动障碍或认知障碍。

在许多国家,无障碍设施也是一项法律要求(例如美国的 ADA、欧洲的 EN 301 549)。

a11y React 开发者最佳实践

1. 使用语义HTML
  • 偏好本土元素
  • 避免使用 div 进行交互式 UI — 屏幕阅读器会跳过它们
2. 确保键盘导航性
  • 每个交互元素都应该可以通过 Tab 和 Enter 访问和操作
  • 慎重使用 tabindex (避免 tabindex="0" 过载)
3. 需要时添加 ARIA 属性
  • 使用 aria-label、aria-hidden、aria-live 为屏幕阅读器提供上下文
  • 但是当语义 HTML 可以完成工作时,不要过度使用 ARIA
4. 为图片提供替代文本
  • 对重要图片使用有意义的 alt=""
  • 使用 alt="" 来隐藏装饰性的
5. 颜色对比度和焦点指示器
  • 确保文本具有高对比度(根据 WCAG AA/AAA 检查)
  • 不要删除焦点轮廓——如果需要,可以自定义它们
6. 表单错误处理
  • 使用 aria-scribeby 链接表单错误
  • 在模糊或提交时进行验证,而不仅仅是在更改时

确保年度合规性的工具

  • axe DevTools(Chrome 扩展程序)——实时分析 WCAG 违规行为
  • eslint-plugin-jsx-a11y — 查找缺失的角色、替代文本、标签陷阱
  • Lighthouse (Chrome/CI) — 审核中的 a11y 评分
  • 屏幕阅读器:NVDA(Windows)、VoiceOver(macOS)、ChromeVox

现实世界的可访问性审计技巧

  • 仅使用键盘即可导航整个应用程序
  • 使用屏幕阅读器浏览常见流程
  • 使用 contrast-ratio.com 等工具测试颜色对比度
  • 避免可能引发运动障碍的动画(尊重prefers-reduced-motion

最终要点:以人为本,确保代码面向未来

React 为你提供工具。这些实践赋予你纪律。

  • 清洁、模块化的组件。
  • 现代功能(钩子、TypeScript、上下文)。
  • 自信的、基于行为的测试。
  • 无障碍且包容的体验。
  • 可扩展的架构和文件结构。
  • 安全的错误处理和性能调整。

当您将这些方法纳入到您的流程中时,您将创建可扩展、持久且令人愉悦的高质量软件。

❌
❌