React 知识清单
一、基础概念
- JSX (JavaScript XML): JavaScript 的语法扩展,允许在 JavaScript 代码中写 HTML。
- 元素 (Elements): React 应用的最小单位,用于描述在屏幕上看到的内容。
- 组件 (Components): 构建 React 应用的基础块,可复用且独立。
二、组件
- 函数组件: 使用 JavaScript 函数创建的组件,可以接受 props。
- 类组件: 使用 ES6 类创建的组件,拥有更多特性,可以有状态 (state) 和生命周期方法。
- 组件的 Props: 组件的输入,用于父子组件之间传递数据。
- 组件的 State: 组件的内部状态,可变。
三、生命周期
- 挂载(Mounting):组件被创建并插入 DOM 中的过程。
- 更新(Updating):组件的 props 或 state 发生变化时的更新过程。
- 卸载(Unmounting):组件从 DOM 中移除的过程。
- 错误处理 (Error Handling): 捕获子组件的错误。
四、Hooks
React 16.8 引入的新特性,用于在函数组件中使用 state 和生命周期等特性。
- useState: 在函数组件中添加状态。
- useEffect:在函数组件中处理副作用(如数据获取、订阅等)。
- useContext: 共享状态的更简单方式。
- useReducer: 用于复杂状态逻辑的 Hook,类似于 Redux。更复杂或大型状态的管理,接受两个参数,第一个参数是一个 reducer,第二个参数是 state 的初始状态。
- useCallback: 缓存回调函数。
- useMemo: 缓存计算结果。
- useRef: 引用 DOM 元素。
- 自定义 Hooks: 封装和共享逻辑。
五、高级指南
- Context: 在整个组件树中共享数据,提供一种在组件树中传递数据的方法,无需显式传递 props。
- 错误边界 (Error Boundaries): 捕获子组件树的 JavaScript 错误。
- Refs: 访问 DOM 节点。
- Fragments: 组合多个元素。
- 高阶组件 (HOCs): 用于组件逻辑复用的高级技术,一种利用函数从组件生成新组件的技术。
- Render Props: 使用函数类型的 Props 共享代码。
六、性能优化
- React.memo: 防止不必要的渲染。
- useMemo 和 useCallback:优化性能,减少不必要的计算和渲染。
- PureComponent: 仅在 Props 或 State 更改时渲染。
- 懒加载: 使用
React.lazy
和Suspense
。
七、路由
- React Router: 用于构建单页面应用(SPA)的路由管理库。
八、状态管理
- Redux:用于全局状态管理的库,常用于大型应用。
- MobX:另一种流行的状态管理库,基于可观察对象。
九、类型检查
- PropTypes:类型检查工具,用于验证组件的 props。
- TypeScript:JavaScript 的超集,提供强类型和编译时类型检查。
十、测试
- Jest:JavaScript 的测试框架,常用于 React 应用。
- React Testing Library:用于测试 React 组件的库,简化的组件测试。
测试类型
- 单元测试 Unit Testing: 测试应用程序中最小的部分(通常是单个函数或组件)。
- 集成测试 Integration Testing: 测试应用程序中多个单元(函数、组件或模块)之间的交互。
- 端到端测试 End-to-End Testing, E2E Testing: 测试整个应用程序的流程,从开始到结束,就像真实用户操作一样。
单元测试 Unit Testing
add.js
function add(a, b) {
return a + b;
}
module.exports = add;
add.test.js
const add = require("./add");
test("adds 1 + 2 to equal 3", () => {
expect(add(1, 2)).toBe(3);
});
集成测试 Integration Testing
考虑一个用户登陆的场景,其中涉及用户输入处理和认证服务:
login.js
function loginUser(username, password, authService) {
if (!username || !password) {
throw new Error("Username and password are required");
}
return authService.authenticate(username, password);
}
module.exports = loginUser;
对于集成测试,你可以模拟 authService
:
login.test.js
const loginUser = require("./login");
const mockAuthService = {
authenticate: jest.fn(),
};
test("calls authenticate with correct credentials", () => {
loginUser("user", "pass", mockAuthService);
expect(mockAuthService.authenticate).toHaveBeenCalledWith("user", "pass");
});
测试本身(在 test 块中)调用了 loginUser
函数,传入一个假设的用户名('user')、密码('pass')以及刚才创建的模拟的认证服务。然后,我们使用 expect
和 toHaveBeenCalledWith
来检查 mockAuthService.authenticate
是否被正确调用,并且传入了正确的用户名和密码。
端到端测试 End-to-End Testing, E2E Testing
对于 E2E 测试,通常会使用工具如 Cypress 或 Selenium。这里是一个使用 Cypress 对网页进行端到端测试的例子:
首先,确保你有一个网页,例如一个带有登录表单的页面:
index.html
<form id="login-form">
<input type="text" id="username" />
<input type="password" id="password" />
<button type="submit">Login</button>
</form>
然后使用 Cypress 进行 E2E 测试:
e2e.test.js
describe("Login Form", () => {
it("successfully logs in", () => {
cy.visit("http://localhost:3000"); // 修改为你的服务器地址
cy.get("#username").type("user");
cy.get("#password").type("pass");
cy.get("#login-form").submit();
// 这里添加对登录成功的断言
});
});
在这个 E2E 测试示例中,Cypress 会打开浏览器,访问指定的 URL,并模拟用户的输入行为,然后提交表单。
十一、最佳实践
- 组件拆分:保持组件小而专注。
- 可维护的代码:遵循清晰的项目结构和编码规范。
- 性能考虑:合理使用状态和 props,避免不必要的渲染。
十二、其他
- Portals: 在父组件的 DOM 层次之外渲染子组件。
- Suspense for Data Fetching: 数据获取的新模式。
- Concurrent Mode: 实验性功能,提高应用响应性。