一、React 生命周期
1、生命周期简介
React 生命周期是指 React 组件从实例创建到销毁的整个过程。其中包含挂载、更新和卸载三个阶段。
2、生命周期分类
React 生命周期可以分为三类:Mounting, Updating, Unmounting。其中 Mounting 指组件加载到 DOM 上,Update 指组件数据改变引起的重新渲染,Unmounting 指组件卸载销毁时。
3、常用生命周期
componentDidMount()
:组件挂载时调用,可以进行 AJAX 请求和 DOM 操作等。
componentDidUpdate()
:组件更新时调用,可以进行更新操作。
componentWillUnmount()
:组件卸载时调用,可以进行一些清理操作。
二、React 的虚拟 DOM
1、什么是虚拟 DOM 虚拟 DOM 是简化版的 DOM,是 React 中组件状态改变后重新渲染组件的关键技术。虚拟 DOM 通过一系列的比较和更新操作,尽可能地减少与真实 DOM 的交互,从而提高页面渲染效率。 2、虚拟 DOM 的优点 (1)提高页面渲染效率,避免了每次修改都涉及到真实 DOM 的操作; (2)简化了操作,提升了开发效率; (3)实现了 diff 算法,可以最小化更新 DOM,从而提高了页面性能。
三、React 组件间通信
1、组件间通信方式
(1)props 静态方式:通过 props 把数据从父组件传递到子组件。
(2)context 跨级方式:通过 context 属性可以在组件树中直接传递数据,跨级传递更加便捷。
(3)自定义事件方式:通过自定义事件向祖先或子孙组件传递信息。
2、props 与 state 的区别
(1)props 是父组件向子组件传递的数据;state 是组件自己的状态数据。
(2)props 是只读的,不允许子组件修改;state 可以由组件自己修改,但需要通过 setState()
方法改变。
四、React 高阶组件(HOC)
1、高阶组件简介 高阶组件是指将一个组件作为参数,并返回一个新组件的函数。 2、高阶组件的作用 (1)代码复用:将多个组件公用的逻辑抽取成一个高阶组件,避免代码冗余; (2)扩展组件功能:将某个组件需要的功能通过高阶组件注入的方式进行扩展; (3)渲染劫持:在不修改组件本身的前提下对组件进行渲染控制。 3、高阶组件示例代码:
// HOC
const withLoginStatus = (WrappedComponent) => {
return class extends React.Component {
constructor(props) {
super(props);
this.state = { isLoggedIn: false };
}
componentDidMount() {
this.setState({ isLoggedIn: true });
}
render() {
const { isLoggedIn } = this.state;
return <WrappedComponent isLoggedIn={isLoggedIn} {...this.props} />;
}
}
}
// 组件
const MyComponent = ({ isLoggedIn }) => (
<p>{isLoggedIn ? '您已登录' : '请登录'}</p>
);
// 使用
const WrappedComponent = withLoginStatus(MyComponent);
ReactDOM.render(<WrappedComponent />, document.getElementById('app'));
五、React 的性能优化
1、虚拟 DOM 优化
(1)减少不必要的渲染:通过 shouldComponentUpdate()
方法来控制是否需要重新渲染组件。
(2)合理使用 React.Fragment:减少多余的 DOM 包裹标签。
(3)使用 key 属性:相同的 key 值可以减少虚拟 DOM 比对时的计算量。
2、其他性能优化
(1)使用 React 生产环境构建:生产环境构建时可以去除开发环境下的调试代码和警告信息。
(2)避免过量渲染:尽可能减少 DOM 操作次数。
(3)优化 JavaScript 代码:避免使用循环嵌套等性能开销大的操作。
代码示例:
class MyComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
if (this.props.text === nextProps.text && this.state.count === nextState.count) {
return false;
}
return true;
}
render() {
return (
<React.Fragment>
<span key="text">{this.props.text}</span>
<button key="btn">{this.state.count}</button>
</React.Fragment>
);
}
}
六、Redux 与 React 结合
1、Redux 基本用法 (1)Action:定义数据操作的类型。 (2)Reducer:定义数据操作,并返回操作后的新数据。 (3)Store:用于管理应用的 State。 2、Redux 与 React 结合示例代码:
// Action
const ADD_TODO = 'ADD_TODO';
const REMOVE_TODO = 'REMOVE_TODO';
// Action Creator
const addTodo = (text) => ({
type: ADD_TODO,
payload: {
text,
},
});
const removeTodo = (id) => ({
type: REMOVE_TODO,
payload: {
id,
},
});
// Reducer
const todos = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [...state, action.payload.text];
case REMOVE_TODO:
return state.filter((item, index) => index !== action.payload.id);
default:
return state;
}
};
// Store
const store = createStore(todos);
// React 组件
const TodoList = ({ todos }) => (
<ul>
{todos.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = { todos: store.getState() };
this.handleAdd = this.handleAdd.bind(this);
this.handleRemove = this.handleRemove.bind(this);
}
componentDidMount() {
this.unsubscribe = store.subscribe(() => {
this.setState({ todos: store.getState() });
});
}
componentWillUnmount() {
this.unsubscribe();
}
handleAdd() {
const text = prompt('请输入待办事项');
if (text) {
store.dispatch(addTodo(text));
}
}
handleRemove(index) {
store.dispatch(removeTodo(index));
}
render() {
const { todos } = this.state;
return (
<React.Fragment>
<TodoList todos={todos} />
<button onClick={this.handleAdd}>新增</button>
</React.Fragment>
);
}
}
ReactDOM.render(<TodoApp />, document.getElementById('app'));