• React面试八股文(第二期)


    React.forwardRef是什么?它有什么作用?

    React.forwardRef 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特别有用:

    • 转发 refs 到 DOM 组件
    • 在高阶组件中转发 refs

    refs的作用是什么,你在什么样的业务场景下使用refs

    • 操作DOM,为什么操作DOM?
    • 场景
      • 图片渲染好后,操作图片宽高。比如做个放大镜功能

    哪些方法会触发 React 重新渲染?重新渲染 render 会做些什么?

    (1)哪些方法会触发 react 重新渲染?

    • setState()方法被调用

    setState 是 React 中最常用的命令,通常情况下,执行 setState 会触发 render。但是这里有个点值得关注,执行 setState 的时候不一定会重新渲染。当 setState 传入 null 时,并不会触发 render。

    class App extends React.Component {
       
      state = {
       
        a: 1
      };
    
      render() {
       
        console.log("render");
        return (
          <React.Fragement>
            <p>{
       this.state.a}</p>
            <button
              onClick={
       () => {
                   this.setState({
        a: 1 }); // 这里并没有改变 a 的值          }}        >          Click me        
            <button onClick={
       () => this.setState(null)}>setState null</button>
            <Child />
          </React.Fragement>
        );
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 父组件重新渲染

    只要父组件重新渲染了,即使传入子组件的 props 未发生变化,那么子组件也会重新渲染,进而触发 render

    (2)重新渲染 render 会做些什么?

    • 会对新旧 VNode 进行对比,也就是我们所说的Diff算法。
    • 对新旧两棵树进行一个深度优先遍历,这样每一个节点都会一个标记,在到深度遍历的时候,每遍历到一和个节点,就把该节点和新的节点树进行对比,如果有差异就放到一个对象里面
    • 遍历差异对象,根据差异的类型,根据对应对规则更新VNode

    React 的处理 render 的基本思维模式是每次一有变动就会去重新渲染整个应用。在 Virtual DOM 没有出现之前,最简单的方法就是直接调用 innerHTML。Virtual DOM厉害的地方并不是说它比直接操作 DOM 快,而是说不管数据怎么变,都会尽量以最小的代价去更新 DOM。React 将 render 函数返回的虚拟 DOM 树与老的进行比较,从而确定 DOM 要不要更新、怎么更新。当 DOM 树很大时,遍历两棵树进行各种比对还是相当耗性能的,特别是在顶层 setState 一个微小的修改,默认会去遍历整棵树。尽管 React 使用高度优化的 Diff 算法,但是这个过程仍然会损耗性能.

    React的事件和普通的HTML事件有什么不同?

    区别:

    • 对于事件名称命名方式,原生事件为全小写,react 事件采用小驼峰;
    • 对于事件函数处理语法,原生事件为字符串,react 事件为函数;
    • react 事件不能采用 return false 的方式来阻止浏览器的默认行为,而必须要地明确地调用preventDefault()来阻止默认行为。

    合成事件是 react 模拟原生 DOM 事件所有能力的一个事件对象,其优点如下:

    • 兼容所有浏览器,更好的跨平台;
    • 将事件统一存放在一个数组,避免频繁的新增与删除(垃圾回收)。
    • 方便 react 统一管理和事务机制。

    事件的执行顺序为原生事件先执行,合成事件后执行,合成事件会冒泡绑定到 document 上,所以尽量避免原生事件与合成事件混用,如果原生事件阻止冒泡,可能会导致合成事件不执行,因为需要冒泡到document 上合成事件才会执行。

    React声明组件有哪几种方法,有什么不同?

    React 声明组件的三种方式:

    • 函数式定义的无状态组件
    • ES5原生方式React.createClass定义的组件
    • ES6形式的extends React.Component定义的组件

    (1)无状态函数式组件 它是为了创建纯展示组件,这种组件只负责根据传入的props来展示,不涉及到state状态的操作
    组件不会被实例化,整体渲染性能得到提升,不能访问this对象,不能访问生命周期的方法

    (2)ES5 原生方式 React.createClass // RFC React.createClass会自绑定函数方法,导致不必要的性能开销,增加代码过时的可能性。

    (3)E6继承形式 React.Component // RCC 目前极为推荐的创建有状态组件的方式,最终会取代React.createClass形式;相对于 React.createClass可以更好实现代码复用。

    无状态组件相对于于后者的区别: 与无状态组件相比,React.createClass和React.Component都是创建有状态的组件,这些组件是要被实例化的,并且可以访问组件的生命周期方法。

    React.createClass与React.Component区别:

    ① 函数this自绑定

    • React.createClass创建的组件,其每一个成员函数的this都有React自动绑定,函数中的this会被正确设置。
    • React.Component创建的组件,其成员函数不会自动绑定this,需要开发者手动绑定,否则this不能获取当前组件实例对象。

    ② 组件属性类型propTypes及其默认props属性defaultProps配置不同

    • React.createClass在创建组件时,有关组件props的属性类型及组件默认的属性会作为组件实例的属性来配置,其中defaultProps是使用getDefaultProps的方法来获取默认组件属性的
    • React.Component在创建组件时配置这两个对应信息时,他们是作为组件类的属性,不是组件实例的属性,也就是所谓的类的静态属性来配置的。

    ③ 组件初始状态state的配置不同

    • React.createClass创建的组件,其状态state是通过getInitialState方法来配置组件相关的状态;
    • React.Component创建的组件,其状态state是在constructor中像初始化组件属性一样声明的。

    React组件的state和props有什么区别?

    (1)props

    props是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性,只能通过外部组件主动传入新的props来重新渲染子组件,否则子组件的props以及展现形式不会改变。

    (2)state

    state的主要作用是用于组件保存、控制以及修改自己的状态,它只能在constructor中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的this.setState来修改,修改state属性会导致组件的重新渲染。

    (3)区别

    • props 是传递给组件的(类似于函数的形参),而state 是在组件内被组件自己管理的(类似于在一个函数内声明的变量)。
    • props 是不可修改的,所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
    • state 是在组件中创建的,一般在 constructor中初始化 state。state 是多变的、可以修改,每次setState都异步更新的。

    React中什么是受控组件和非控组件?

    (1)受控组件 在使用表单来收集用户输入时,例如