新闻动态

一名中/高级前端工程师的自检清单-React 篇

常见问题 发布者:ou3377 2021-12-15 09:10 访问量:161

你真的了解 React 吗?我们在面试中往往涉及 React 时,第一个问题就是“解释 React 是什么”。解释一种技术是什么,在面试中也是非常常见的引起 话题的题目。本篇文章我就带你掌握这一类概念题的解答技巧。

一. 说说对 React 的理解,有哪些特性

官方的解释:React 是一个 UI 库,它的核心思想是UI=F(data), 即界面的呈现是由函数传入的参数决定的

开发者不再需要关心界面时如何渲染的,只要关心数据的生成和传递,这大大提高的开发者的开发效率,节省了开发时间

其次 React 设计的

  • 使用类似 HTML 的JSX语法来描述视图
  • 通过虚拟DOM修改真实DOM
  • 通过setState修改数据
  • 在不同的生命周期阶段做不同的事
  • 源码底层对真实 DOM 事件进行封装,使用事件委托的方式来捕获 DOM 事件
  • ....

等特性进一步简化的 真实 DOM 操作的复杂性

二. 说说真实 DOM 与虚拟 DOM 的区别,优缺点

图片虚拟DOM

2.1 虚拟 DOM 是什么

  • 真实DOM就是我们在浏览器开发者工具中看到的DOM结构
  • 虚拟DOM简单来说就是 JS 对象,此对象中的字段包含了对真实DOM的描述:
    • type:是什么标签/元素
    • props:标签/元素有哪些属性
    • children:是否有子元素

图片a

2.2 虚拟 DOM 大概是如何工作的

当 DOM 操作(渲染更新)比较频繁时,

React 底层会先将前后两次的虚拟DOM 树进行对比,

定位出具体需要更新的部分,生成一个补丁集

最后只把“补丁”打在需要更新的那部分真实DOM 上,实现精准的“差量更新”。

2.3 虚拟 DOM 的优点

  1. 解决了频繁操作真实 DOM 的低效率工作-不直接操作 DOM,数据驱动视图,也在一定程度上提升了性能
  2. 解决了扩平台开发的问题,因为虚拟 DOM 描述的东西可以是真实 DOM,也可以是安卓界面。IOS 界面等等,这就可以对接不同平台的渲染逻辑。从而实现"一次编码,多端运行"(如 React,React Native)

2.4 虚拟 DOM 的缺点

如果当虚拟 DOM 的构建和diff的过程相对复杂(比如很多递归遍历等操作),那么虚拟 DOM 的 JS 计算是比较耗时的

三. 说说 Diff 算法

图片Diff算法

一般的原始 diff 思路算法复杂度是O(n^3),即循环递归进行树节点的一一对比

但 React 的 diff 算法是 O (n) 复杂度的思路

当对比两棵虚拟 DOM 树时,React 首先比较两棵树的根节点。不同类型的根节点元素会有不同的形态

当对比两个相同类型的 React 元素时,React 会保留 DOM 节点,仅比对及更新有改变的属性。

  1. 当根节点为不同类型的元素时,React 会拆卸原有的树并且建立起新的树,这大大减少了 Diff 过程中冗余的递归操作
  2. 当对比两个相同类型的 React 元素时,React 会保留 DOM 节点,仅比对及更新有改变的属性
  3. 列表形式的子元素比较:React 引入了 key 属性。当子元素拥有 key 时,React 使用 key 来匹配原有树上的子元素以及最新树上的子元素,如果 key不同 不同则会拆卸原有的 key 节点并且建立起新的 key 节点

详细内容请参考React 官方文档- Diffing 算法[2]

四. 说说 React 声明周期有哪些不同阶段,每个阶段对应的方法是什么

图片image.png

4.1 创建阶段

  1. constructor():组件的构造函数,组件更新到界面上之前会先调用

    • 用于初始化内部状态,很少使用
    • 唯一可以直接修改 state 的地方
  2. static getDerivedStateFromProps(nextProps, prevState):用于从外部的属性去初始化一些内部的状态

    • 当 state 需要从 props 初始化时使用
    • 尽量不要使用,维护 state/props 状态一致性会增加复杂度
    • 每次 render 都会调用
    • 典型场景: 表单控件获取默认值
  3. render()::组件必须定义的一个生命周期方法,用来描述 虚拟 DOM 结构

  4. componentDidMount(): 用于数据请求,定义一些外部资源等等副作用

    • UI 渲染完成后调用
    • 只执行一次
    • 典型场景:获取外部资源

4.2 更新阶段

  1. static getDerivedStateFromProps(nextProps, prevState)
  2. shouldComponentUpdate(nextProps, nextState):告诉组件是否需要重新渲染,用于性能优化,比如判定指定 props 发生改变,组件才进行重新渲染
    • 决定虚拟 DOM 是否需要重绘
    • 一般可以由 PureComponent 自动实现
    • 典型场景:性能优化
  3. render()
  4. getSnapshotBeforeUpdate(prevProps, prevState)
    • 在最近一次渲染输出(提交到 DOM 节点)之前调用,state 已更新
    • 与 componentDidUpdate 搭配使用
    • 典型场景:捕获 render 之前的 DOM 状态
  5. componentDidUpdate(prevProps, prevState)
    • 每次 UI 更新时被调用
    • 典型场景:页面需要根据 props 变化重新获取数据

4.3 卸载阶段

  1. componentWillUnmount(): 做些资源释放,卸载副作用的事情
  • 此方法中可以执行必要的清理操作,例如,清除 timer,取消网络请求或清除在

详细内容请参考React 知识体系之生命周期及使用场景[3]

五. 说说对 State 和 Props 的理解,有什么区别

  • state用于组件内部数据传递,state 数据可以通过this.setSate或者useState进行修改

  • props用于组件外部组件数据传递,props不能直接修改.主要使用场景是:

    • 兄弟组件通信
    • 父子组件通信
    • "爷孙组件"组件通信
  • props的使用范围虽然更加广泛,但也有其局限性:对于嵌套层次较深的组件,如果使用props传递数据,会导致代码冗余,增加数据传递的复杂度

六. super 和 super(props)有什么区别

在 JavaScript 中,super 指的是父类构造函数。(在我们的示例中,它指向 React.Component 实现。)

在调用父类的构造函数之前,你是不能在 constructor 中使用 this 关键字的。JavaScript 不允许这个行为

class Checkbox extends React.Component {
  constructor(props) {
    // 

关键字:react

http://m.chenzhankj.com/cjwt/821.html