react

我从2015在外企因工作需要使用了react native,然后就踏上了前端的不归路,这几年工作中都有使用react 开发项目,虽然我面试别人很少问这方面的问题,但是自己去被别人面还是经常会有人考我,特别是阿里系的岗位。

组件的state和props有何不同?

  • props 由父组件传递给子组件,就子组件而言,props 是不可变的;
  • State 是一种数据结构,用于组件挂载时所需数据的默认值。

调用 setState 发生了什么?

  • 将传入的参数对象与组件当前的状态合并;
  • 触发调和过程,根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面;
  • 自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染,按需更新,而不是全部重新渲染。

React 中 keys 的作用是什么?

  • key 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识,我们需要保证某个元素的 key 在其同级元素中具有唯一性。
  • 在 Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。
  • 此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。

react 生命周期函数有哪些?

  • 初始化阶段:
    • getDefaultProps:获取实例的默认属性
    • getInitialState:获取每个实例的初始化状态
    • componentWillMount:组件即将被装载、渲染到页面上
    • render:组件在这里生成虚拟的 DOM 节点
    • componentDidMount:组件真正在被装载之后
  • 运行阶段:
    • componentWillReceiveProps:组件将要接收到属性的时候调用
    • shouldComponentUpdate:组件接受到新属性或者新状态的时候
    • componentWillUpdate:组件即将更新不能修改属性和状态
    • render:组件重新描绘
    • componentDidUpdate:组件已经更新
  • 销毁阶段:
    • componentWillUnmount:组件即将销毁

react怎么从虚拟dom中拿出真实dom?

refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄, 我们可以通过this.$refs 获取对应我们标记的dom元素。

React如何性能优化?

  • 减少对真实DOM的操作;
  • 能用const声明的就用const;
  • 给遍历的DOM上加上唯一的key;
  • 重写shouldComponentUpdate来避免不必要的dom操作;
  • DOM里少用箭头函数;
  • bind 函数尽量写在constructor,避免每次render重新bind;
  • 如果是用webpack搭建环境的话,通过适当拆包和压缩来优化。

react diff 原理?

它的作用是计算出Virtual DOM中真正变化的部分,并只针对该部分进行原生DOM操作,而非重新渲染整个页面。

将Virtual DOM树转换成actual DOM树的最少操作的过程 称为 调和,diff算法是调和的具体实现。

  • React 通过分层求异的策略,对 tree diff 进行算法优化;
  • React 通过相同类生成相似树形结构,不同类生成不同树形结构的策略,对 component diff 进行算法优化;
  • React 通过设置唯一 key的策略,对 element diff 进行算法优化;

建议:

  • 在开发组件时,保持稳定的 DOM 结构会有助于性能的提升;
  • 在开发过程中,尽量减少类似将最后一个节点移动到列表首部的操作,当节点数量过大或更新操作过于频繁时,在一定程度上会影响 React 的渲染性能。

react虚拟DOM实现原理?

  • 用 js对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档中;
  • 当状态变更的时候,重新构造一棵新的对象树,对比新旧虚拟DOM树,记录两棵树差异;
  • 把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。

Redux的实现流程

  • 用户页面行为触发一个Action,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action;
  • Reducer 会返回新的 State,view根据state触发重新渲染。

react-redux的实现原理

Redux作为一个通用模块,主要还是用来处理应用中state的变更,通过react-redux做连接,可以在React+Redux的项目中将两者结合的更好。

react-redux是一个轻量级的封装库,它主要通过两个核心方法实现:

  • Provider:从最外部封装了整个应用,并向connect模块传递store。
  • Connect:
    • 包装原组件,将state和action通过props的方式传入到原组件内部。
    • 监听store tree变化,使其包装的原组件可以响应state变化

react如何实现复用?

封装与复用是一个经典的话题,低效的工作方式是我们加班加点最主要的原因之一,封装与复用帮助我们把能改变的做好。

render-props 和 HOC 作为 react 中的代码复用方式,都得到了广泛的使用,多数情况下, 两者是可以互换的,主要区别在于:

  • render props 是细粒度的代码复用,如某个 render 函数里的某个组件依赖一些属性和方法时;
  • hoc 是粗粒度的代码复用,可以扭转整个组件的行为,外部调用和内部使用,都不会造成影响。

react hooks 是react 16.8 引入的特性,允许在不写class的情况下操作state 和react的其他特性。

通过自定义hook把公共的逻辑提取出来,让逻辑在多个组件之间共享。

Hooks 的出现本质是把这种面向生命周期编程变成了面向业务逻辑编程,你不用再去关心本不该关心的生命周期。

HOC 和 Render Props 还是有存在的必要,一方面是支持 React Class,另一方面,它们不光适用于纯逻辑封装,很多时候也适合逻辑 + 组件的封装场景,虽然此时使用 Hooks 也可以,但是会显得啰嗦点。

小结

国内有关react 的教程和源码分析相对没有vue多,而且目前国内使用vue的新项目更多,我这几年面试一般都会跟面试官说我对vue更熟悉,所以问react的问题就比较少。