frameWork
React 生命周期
React 组件的生命周期分为三个主要阶段:挂载(Mounting)、更新(Updating) 和 卸载(Unmounting)。每个阶段都有一系列生命周期方法,用于在特定时刻执行操作。
挂载阶段(组件被创建并插入 DOM 中):
constructor(props)
:构造函数,用于初始化组件状态和绑定方法。通常在此阶段初始化state
和ref
。
constructor(props) {
super(props);
this.state = { count: 0 };
}
static getDerivedStateFromProps(props, state)
:在每次渲染前调用,返回一个对象来更新状态,或者返回null
表示不更新状态。render()
:这是唯一一个必需的方法,负责渲染组件内容。它返回虚拟 DOM。componentDidMount()
:组件挂载后调用。适合执行副作用操作,如数据获取、订阅等。
componentDidMount() {
fetchData().then(data => this.setState({ data }));
}
更新阶段(组件因状态或属性变化而重新渲染):
static getDerivedStateFromProps(props, state)
:同挂载阶段,允许根据新的 props 或 state 更新 state。shouldComponentUpdate(nextProps, nextState)
:在每次更新前调用,判断是否需要重新渲染。默认返回true
,如果性能优化需求,可以返回false
来避免不必要的渲染。
shouldComponentUpdate(nextProps, nextState) {
return nextState.count !== this.state.count;
}
render()
:同挂载阶段,渲染组件 UI。getSnapshotBeforeUpdate(prevProps, prevState)
:在变更被提交到 DOM 之前调用,适合获取一些 DOM 状态(如滚动位置)。componentDidUpdate(prevProps, prevState, snapshot)
:在组件更新后调用。用于执行副作用操作,如网络请求或 DOM 更新。
卸载阶段(组件从 DOM 中移除):
componentWillUnmount()
:组件卸载之前调用,适合清理订阅、计时器等副作用。
componentWillUnmount() {
clearInterval(this.timerID);
}
React 性能优化
shouldComponentUpdate
: 用于控制组件是否在状态或属性更新时重新渲染。可以通过比较新旧 props
和 state
来决定是否渲染组件。如果某些更新不影响 UI,可以返回 false
来避免不必要的渲染。
shouldComponentUpdate(nextProps, nextState) {
return nextState.someValue !== this.state.someValue;
}
React.memo
: 是一个高阶组件,用于优化函数组件的性能。它通过浅比较 props
来避免不必要的重新渲染。只要组件的 props
没有变化,React 就会跳过重新渲染。
const MyComponent = React.memo(function MyComponent(props) {
return <div>{props.value}</div>;
});
useMemo
: 用于缓存计算结果,只有当依赖项发生变化时才会重新计算,适用于性能消耗大的计算。
const expensiveComputation = useMemo(() => computeExpensiveValue(value), [value]);
useCallback
: 用于缓存回调函数,避免每次渲染时都重新创建函数实例,适用于作为子组件 props
传递的回调函数。
const memoizedCallback = useCallback(() => {
doSomething(value);
}, [value]);
状态管理
在大型 React 项目中,通常使用 Redux 或 React Context 来管理全局状态。
Redux:
- 优点:提供了高度可预测的状态管理,适用于大型应用,能够与中间件(如
redux-thunk
或redux-saga
)结合,支持异步操作和副作用处理。能够通过DevTools
进行状态调试。 - 缺点:对于小型应用,Redux 配置较复杂,代码量大,使用起来需要更多的样板代码。
React Context:
- 优点:使用简单,直接集成于 React 中,不需要额外的库,适用于小型或中型项目的状态管理。
- 缺点:不适合管理大量动态状态,性能可能会受到影响,因为每次更新 Context 都会重新渲染所有依赖它的组件。
Vue
Vue 响应式原理
Vue 的响应式系统是基于 Object.defineProperty 和 Proxy(Vue 3 中采用 Proxy
)实现的。它会在数据对象的每个属性上添加 getter 和 setter,当属性被访问或修改时,Vue 会自动跟踪依赖,并在属性值变化时触发视图更新。
- getter:访问属性时触发,用于收集依赖。
- setter:修改属性时触发,用于通知依赖更新。
当数据变化时,Vue 会重新渲染视图,确保视图与数据保持一致。
Vue 生命周期
Vue 组件的生命周期钩子分为创建、挂载、更新、销毁四个阶段:
创建阶段:
beforeCreate
:实例初始化后,数据观测和事件配置前调用。created
:实例创建完成后调用,此时数据已经被观测,属性和方法可用。
挂载阶段:
beforeMount
:模板编译和挂载前调用。mounted
:组件挂载到 DOM 后调用,适合进行 DOM 操作或请求数据。
更新阶段:
beforeUpdate
:数据变化前调用,适合在视图更新前执行某些操作。updated
:数据变化后调用,适合在视图更新后执行操作。
销毁阶段:
beforeDestroy
:组件销毁前调用,适合清理副作用(如定时器、事件监听器)。destroyed
:组件销毁后调用,清理资源。
Vuex 状态管理
Vuex 是 Vue 官方提供的状态管理库,适用于中大型 Vue 项目,用于集中管理所有组件的状态。
使用:Vuex 提供了 state、mutations、actions、getters 等 API 来管理全局状态。通过 commit
触发 mutations 更新状态,通过 dispatch
触发 actions 执行异步操作。
优点:有统一的状态管理和明确的单向数据流,适合大型应用。通过 devtools
可以进行状态跟踪和调试。
缺点:配置较复杂,过多的状态管理代码可能导致维护困难,适用于复杂的中大型应用。
框架优化
组件性能优化
React:
- 使用
shouldComponentUpdate
或React.memo
来避免不必要的重新渲染。 - 使用
useMemo
和useCallback
缓存计算结果和回调函数,减少不必要的计算和函数实例创建。 - 使用虚拟化技术(如 React Virtualized)来渲染长列表,避免渲染不在视口内的元素。
Vue:
- 使用
v-once
或v-memo
缓存静态内容,避免重复渲染。 - 使用
computed
属性来缓存计算结果,避免每次渲染时重新计算。 - 避免在模板中进行复杂的计算或方法调用,将这些逻辑移至
data
或computed
中。
虚拟 DOM
虚拟 DOM 是一种在内存中创建与真实 DOM 结构相似的虚拟表示的技术。当数据发生变化时,框架会更新虚拟 DOM,然后通过与当前虚拟 DOM 的对比(diffing)找出最小的变化,最后只更新这些变化部分到真实 DOM 上。
提升性能的方式:
- 减少直接操作 DOM,因为 DOM 操作开销较大,虚拟 DOM 将多次渲染和对比的开销集中处理。
- 通过 diff 算法找到最小差异并只更新差异部分,避免重绘整个页面。