react面试题

https://fd.svsva.cn/wjd

React的理解 有哪些特性

一、什么是虚拟Dom,实现原理,区别,优缺点?

Diff算法说明

Fiber

二、函数组件与类组件区别

三、state和props的区别

super和super(props)的区别

类组件生命周期函数

四、setState执行机制

五、react事件机制

六、react事件绑定方式class

八、React组件通信

九、React中refs是什么

十、React中的key作用

11、受控组件、非受控组件

12、什么是高阶组件

13、什么是 JSX

14、不能直接更新state数据

15、什么是React Hooks

16、react中引入css方式

17、redux理解,以及工作原理

React中间件

18、React中router的原理、解释、传参方式?

20、immutable 不变的

21、类组件render方法原理

22、React组件复用

23、获取页面滚动距离

22、性能优化、避免不必要的render渲染

23、怎样理解三次握手,四次挥手

JS基础部分

JS高级

作用域的理解

手写Promise

面试题总结

JS面试常问

项目亮点

React的理解 有哪些特性

​ React是一个构建用户界面的 Javasript 库,只提供了UI层面的解决方案

​ 主要使用组件设计模式、声明式编程和函数式编程。

​ 声明式编程:他只关心你要做什么 而不是怎么做

​ component:react中一切皆为组件 把整个应用逻辑拆分成小部分,每个小的部分称为组件

​ 优点:可复用、可组合、易维护

使用jsx语法, 它具备了js的能力,可以将HTML结构嵌入JS代码中但是不能直接被浏览器识别,最终会被 babel编译为合法的 JS语句。

遵循单向数据流原则。比双向数据绑定更安全速度更快

使用虚拟DOM来有效的操作DOM,。虚拟Dom原理…

一、什么是虚拟Dom,实现原理,区别,优缺点?

  1. 虚拟Dom是真实Dom在内存中的表示

  2. 本质上是以 JavaScript 对象形式存在,是对 真实DOM 的描述

  3. 数据状态更新,会记录新树与旧树的差异,把差异更新到真实Dom中

  4. 区别在于虚拟Dom不会进行重排重绘,而真实Dom会频繁进行重排重绘

  5. 文档对象模型,是一个结构化文本的抽象,在页面渲染出的每一个结点都是一个真实DOM

  6. 真实Dom优势在于:易用,

  7. 缺点:效率低:解析速度慢,内存占用量高, 性能差:频繁操作Dom导致重排重绘

  8. 虚拟Dom优点:简单方便,避免的真实Dom的频繁更新,减少多次重绘重排,提高了性能

    跨平台使用:借助虚拟Dom,一套代码多端使用

  9. 缺点:首次渲染大量虚拟Dom,由于多了一些计算,加载会较慢,无法满足针对性能要求极高的应用

  10. 底层是一套diff算法

Diff算法说明

  1. tree diff -----将整棵树分层,对同层级的节点进行比较,说对比两个标签 判断是否相同,如果不同直接删除重建

  2. conponent diff------对比同层级节点的类型,如果有不同 则直接删除节点,重新创建新的节点 比如说conponent A 换成了 conponent B 虽然长得很像,但是也会删除A 再创建B

  3. element diff 比较同层级中子节点默认按照下标对比,如果设置了key,通过key属性指定唯一标识进行对比

    如果key是相同的只需要把旧集合节点更新到新的节点

    1. key应该是唯一的
    2. key不能是随机值
    3. 使用index下标作为key时 对性能没有优化
    4. 在实际开发中 多用id指定key值

    key是唯一表示,如果渲染列表数据时,

Fiber

JS引擎和页面渲染引擎两个线程是互斥的,其中一个线程执行的时候,另一个只能挂起,如果JS线程长时间占用着主线程,那么页面渲染引擎就不得不原地等待,时间明显超过16ms了,浏览器就会阻塞页面的渲染,界面长时间不更新 会导致页面响应速度变差,用户会觉得卡顿 掉帧。当js引擎渲染组件时,从开始到渲染完成是一气呵成的无法中断,采用遍历递归来对比虚拟Dom树,找出需要变动的节点,然后同步的更新他们,如果组件较大,那么js线程会一直执行 等到dom树计算完成后,才会把控制权交给渲染线程,如果递归花费100ms,那么这100ms浏览器是无法相应的,代码执行时间越长 卡顿越明显,CPU的瓶颈

为了解决主线程长时间占用的问题,react16引入了Fiber数据结构

一个 fiber 就是一个 JavaScript 对象

**核心:**Fiber 架构的核心即是可中断、可恢复、优先级

利用 时间切片 解决的问题就是,划分优先级 把长任务分拆到每一帧中,拆分成一个个小的任务块,将同步的更新变为可中断的异步更新

通过ConCurrent Mode,通过合理的调用机制来调控时间,指定任务执行时间 从而降低页面卡顿的概率** 同时必须结合event loop的机制来操作,如果一个小任务执行js解析 页面绘制 没有超过16.67ms 就会执行 requestIdleCallback 中注册的任务

react面试题_第1张图片react面试题_第2张图片

二、函数组件与类组件区别

类组件与函数组件的区别在于,组件是否有状态,

类组件

  1. 类组件通过ES6 类的编写形式编写代码 此类继承 React.Component方法
  2. 如果想访问父组件的数据必须通过props接收,通过this.props访问l
  3. 通过state在组件内部维护数据
  4. 直接说 state和props的区别…+生命周期…

函数组件

  1. 在使用类组件时 需要实例化,比较消耗性能
  2. 在没有hooks之前只能使用这种方法维护状态,
  3. 从react16.8之后有了hooks的出现…
  4. 函数组件使用时直接取函数的返回值即可,在能满足需求的情况下,多使用函数组件
  5. 而且目前比较推崇函数式编程

类组件:

//状态管理不同
类组件可以通过this.setState 来管理状态信息
//生命周期:
render  //渲染DOM结构
componentDidMount  //组件挂载到真实DOM节点后执行
componentDidIpdate   //组件更新结束后触发
componentWillUnmount  //组件卸载时触发

函数组件:

/状态管理不同
函数组件通过useState声明管理状态信息
通过useEffect模拟类组件声明周期函数

三、state和props的区别

核心:组件的显示形态可以由数据状态和外部参数 所决定,数据状态就是state

总结:

  1. state和props都是js对象
  2. 两者都保存着影响页面渲染结果的信息
  3. props是外部组件传递过来的数据,数据状态无法改变
  4. state是在组件内部,数据状态由组件本身进行管理,数据状态可以改变
  5. 类组件通过setState修改,函数组件结合hooks进行修改

super和super(props)的区别

在React中,类组件是基于ES6,所以在constructor中必须用super

在调用super中,无论是否传入props,React内部都会将props赋值给组件实例props属性中

传入props原因是 在子构造函数中能够使用this.props来获取传入的值

类组件生命周期函数

挂载阶段:

constructor

​ 实例过程中自动调用的方法,在方法内通过super来获取父组件的 props

​ 初始化组件内部state数据

getDerivedStateFromProps

无论state、props是否变化都会执行的方法,参数1 为即将更新的的props数据,参数2 上一个state状态,可以在其中做逻辑处理,防止无用的state更新

render

​ 类组件中必须使用的方法 渲染DOM的方法 可以使用state和props数据

​ 注意不能再render中调用setState 会造成死循环

conponentDidMount

组件挂载完毕后执行的方法 可以做一些事件监听、发送ajax请求

更新阶段:

getDerivedStateFromProps:—

shouComponentUpdate

​ 告诉组件 基于本身props和state是否需要重新渲染组件,默认情况返回true

​ 参数1 NextPorps 参数2 NextState 可以做逻辑处理判断组件是否需要更新

render:------

getSnpshotBeforeUpdate:

返回一个 Snapshot值 可以获取组件更新前的一些信息 作为cmponentDiUpdate的第三个参数传入

componentDidUpdate

​ 组件更新结束后执行,可以根据state和props的变化做处理

卸载阶段:

componentWillUnmount

​ 在组件卸载前触发 可以卸载事件 关闭定时,取消订阅的网络请求器,一旦组件实例被卸载,不会再次被挂载,而只会重新创建

四、setState执行机制

第一种:通过onclick事件,执行this.setState方法,进行更新state状态,重新执行render函数从而导致视图更新

第二种:setstate异步状态,,在组件中使用setstate时为异步状态,如果想拿到最新的状态,需要传递第二个参数,setstate在原生Dom中或setTimeout中呈现同步状态

第三种:批量更新状态,对同一个值进行多次setState时会产生覆盖,更新策略只会取最后一次的执行结果,而在setTimeout和原生dom中不会出现覆盖

五、react事件机制

  • 为了解决跨浏览器兼容性问题React基于浏览器的事件机制自身实现了一套事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等

    组件注册的事件最终会绑定在document这个 DOM上,而不是 React组件对应的 DOM,从而节省内存开销,它拥有和浏览器原生事件相同的接口,包含preventdefault()

六、react事件绑定方式class

  1. render方法中使用bind

  2. render方法中使用箭头函数

  3. constructor中bind

  4. 定义阶段使用箭头函数绑定

  5. 区别:方法1和方法2简单,

    方法3.该属性值传递给组件时,会导致渲染,有性能浪费

    方法4.使用箭头函只会生成一个实例,所以方法4对于开发更友好

八、React组件通信

分类:

  • 父组件向子组件传递
  • 子组件向父组件传递
  • 兄弟组件之间的通信
  • 父组件向后代组件传递
  • 非关系组件传递
  1. 父传子:父组件通过标签属性传递参数,子组件通过props接收父组件传递过来的数据
  2. 子传父:父组件向子组件传递一个函数,子组件通过函数的回调传递参数给父组件,父组件在做状态处理
  3. 兄弟组件之间通信,父组件作为中间件实现数据互通
  4. 父组件向后代组件通信类似全局数据,使用React.creactContext创建一个context,通过创建好的context下的Provider来创建全局数据源,通过value属性向下传递数据,其他组件通过Consumer来使用全局数据
  5. 非关系组件建议使用redux来管理状态

总结:React遵循单项数据流,组件自身不会改变接收到的状态,当状态发生变化时候,组件使用新的值,而不是修改之前的值。数据存储的位置都是在上级组件中

九、React中refs是什么

核心:允许访问Dom节点和React元素的一种方法,,如果是渲染组件则返回的是组件实例,如果为dom则返回具体的dom节点,

类组件:通过React.createRef创建, 函数组件通过useRef()创建

可以给组件添加ref属性来使用 使用ref对象中的currect属性来访问react元素,

该属性的值是一个回调函数,接收作为第一个参数的底层Dom元素或组件挂载实例

不能在函数组件上使用ref属性,因为他们并没有实例

但是过多使用refs会造成节点暴露,违反组件封装原则

使用场景:操作Dom元素,获取聚焦、内容选择、内容设置、媒体播放等等

十、React中的key作用

key的作用

key 是 React 的虚拟 DOM 对象的唯一标识,在页面发生更新渲染时,判断是新创建的元素还是修改的元素,从而避免不必要的渲染

即当状态数据发生变化时,React 会根据 新的数据 生成 新的虚拟DOM,随后再进行新虚拟DOM旧虚拟DOM 之间的差异比对(diff)。

在 diff 算法中,存在三大策略,分别是:

  • 树策略(tree diff)- 同层比较节点的数量和标签
  • 组件策略(component diff)- 同层比较节点的属性和值
  • 元素策略(element diff)- 对于同一层级的一组子节点,区分是否出现新增、删除、移动的情况(可通过添加唯一 key 更好的区分)

总结

  1. key应该是唯一的
  2. key不能是随机值
  3. 使用index下标作为key时 对性能没有优化
  4. 在实际开发中 多用id指定key值

流程图:

react面试题_第3张图片

11、受控组件、非受控组件

受控组件:标签