react面试题

389 阅读4分钟

汇总,涉及原文之后会标注原文链接

有错误及时指正

合成事件和原生事件

以react为例

合成事件:

React有自己的一套事件机制,它重新封装了绝大部分的原生事件。合成事件采用了事件池,这样做可以大大节省内存,而不会频繁的创建和销毁事件对象。

react并不是将click事件绑在该div的真实DOM上,而是在document处监听所有支持的事件,当事件发生并冒泡至document处时,React将事件内容封装并交由真正的处理函数运行。

什么是虚拟dom?
虚拟DOM就是普通的js对象。是一个用来描述真实dom结构的js对象,因为它不是真实的dom,所以才叫做虚拟dom。
虚拟dom的好处:虚拟dom可以很好地跟踪当前dom状态,因为它会根据当前数据生成一个描述当前dom结构的虚拟dom,然后数据发生变化时,有生成一个新的虚拟dom,而两个虚拟dom恰好保存了变化前后的状态。然后通过diff算法,计算出当前两个虚拟dom之间的差异,得出一个更好的替换方案。

原生事件:

就是js的原生事件,如通过document.addEventListener来设置的监听事件

原生与合成事件触发顺序

无论是否是对于同一元素监听的同种类型事件,原生事件总是比合成事件先触发。这是由于上面我们说到的合成事件最终都会绑定到documnet DOM上导致的,当合成事件监听到后,总是冒泡到document才会真正触发。而documnet DOM上监听的原生事件则总是最后触发。

reac生命周期

初始化

constructor页面初始化阶段,使用该生命周期必须要调用super函数,否则this指向会报错; componentwillMount表示dom渲染前; render渲染 componentDidMont,挂载期,dom元素挂载完成后执行,一般在这里进行ajax请求;

更新

componentwillreceiveprops监听prop变化, shouldComponentUpdate,更新前,该生命周期返回一个布尔值,返回true继续更新,返回false停止更新,一般在该生命周期进行性能优化; componentwillupdate数据更新前

销毁

componentDidUpdate,更新后,在更新结束后调用,该生命周期有两个参数,一个是旧的state,一个是旧的props; componentDidUnMont,销毁阶段,在组件被销毁前调用,一般用来关闭事件监听,以及清除定时器,延时器的调用;

最新更新生命周期

getSnapShotBeforeUpdate--componentwillupdate static getDerivedStateFromProps--componentwillreceiveprops(返回null,不更新)

函数组件优化方式

优化主要优化在哪里

  1. 减少render渲染次数,因为react换时间最重的就是reconction(diff),所以只要减少reconction就可以。

怎样去减少渲染次数?

useMemo 的使用场景主要是用来缓存计算量比较大的函数结果,可以避免不必要的重复计算,如果计算量不大,也就不需要用了, 甚至有可能还会不如每次计算。

  1. 减少计算量,主要是减少重复计算,对于函数式组件来说,每次 render 都会重新从头开始执行函数调用。

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。

  1. 合理的拆分组件,每次更新都会重新render一下组件,如果组件太大,每次渲染消耗的就更多,而且状态混乱不容易维护,颗粒度越小越好维护。

react组件通讯方式

父传子:子组件使用props接收

子传父:使用回调函数

跨级组件:使用redux/context

redux如何处理异步

redux是如何工作的?

1. 通过 dispatch(action) -> 中间件 -> reducer处理数据 -> 改变store -> 使用subscribe()监听store改变更新视图 的方式管理状态

2. 将所有状态存储在一个store对象里面

3. reducer为纯函数,而异步操作由于结果的不确定性所以含有副作用,所以需要特殊处理

redux中间件

redux-thunk、redux-saga

redux-thunk: 改造store.dispatch,解决异步操作

1.    redux-thunk中间件允许action是一个方法

2.    中间件收到action后会执行action方法并将结果提供给reducer

3.    action混乱导致不易维护

redux-saga:

1.    saga会监听action并基于这个action执行Effects操作

2.    Effects提供灵活的API,包括阻塞、非阻塞调用,取消、等待、race等操作

3.    方便隔离并执行异步操作,并易于测试

类组件是如何获取redux中的值

使用mapStateToProps、mapDispatchToProps

`let mapStateToProps = (state) => {

  return {

    propName: state.user,

  };

}; `  

`let mapDispatchToProps = (dispatch) => {

  return {

    dispatchName: (data) => dispatch(reducer(data)),

  };

};`