zoukankan      html  css  js  c++  java
  • react相关面试题

    React 的核心流程可以分为两个部分:

    reconciliation (调度算法,也可称为 render): // 调和

        更新 state 与 props;

        调用生命周期钩子;

        生成 virtual dom;

        这里应该称为 Fiber Tree 更为符合;

        通过新旧 vdom 进行 diff 算法,获取 vdom change;

        确定是否需要重新渲染

      commit:

        如需要,则操作 dom 节点更新;

    constructor ====》 初始化state
    componentWillMount  ==== 》getDerivedStateFromProps // 当新 props 中的 data 发生变化时,同步更新到 state 上
    componentDidMount ====》进行事件监听,数据的请求
    componentWillUpdate === 》 getSnapshotBeforeUpdate componentDidUpdate ==== 》 当 id 发生变化时,重新获取数据 shouldComponentUpdate ====》 优化渲染的性能,return false 阻止后面的逻辑 componentWillReciveProps ==== 》少使用,使用getDerivedStateFromProps  componentWillUnmount ====》 解绑事件

    在新版本中,React 官方对生命周期有了新的 变动建议:

    • 使用getDerivedStateFromProps 替换componentWillMount
    • 使用getSnapshotBeforeUpdate替换componentWillUpdate
    • 避免使用componentWillReceiveProps

    其实该变动的原因,正是由于上述提到的 Fiber。首先,从上面我们知道 React 可以分成 reconciliation 与 commit 两个阶段,对应的生命周期如下:

    • reconciliation:

      • componentWillMount
      • componentWillReceiveProps
      • shouldComponentUpdate
      • componentWillUpdate
    • commit:

      • componentDidMount
      • componentDidUpdate
      • componentWillUnmount

    在 Fiber 中,reconciliation 阶段进行了任务分割,涉及到 暂停 和 重启,因此可能会导致 reconciliation 中的生命周期函数在一次更新渲染循环中被 多次调用 的情况,产生一些意外错误。

    新版的建议生命周期如下:

    class Component extends React.Component {
      // 替换 `componentWillReceiveProps` ,
      // 初始化和 update 时被调用
      // 静态函数,无法使用 this
      static getDerivedStateFromProps(nextProps, prevState) {}
      
      // 判断是否需要更新组件
      // 可以用于组件性能优化
      shouldComponentUpdate(nextProps, nextState) {}
      
      // 组件被挂载后触发
      componentDidMount() {}
      
      // 替换 componentWillUpdate
      // 可以在更新之前获取最新 dom 数据
      getSnapshotBeforeUpdate() {}
      
      // 组件更新后调用
      componentDidUpdate() {}
      
      // 组件即将销毁
      componentWillUnmount() {}
      
      // 组件已销毁
      componentDidUnMount() {}
    }
    

      使用建议:

    • constructor初始化 state;
    • componentDidMount中进行事件监听,并在componentWillUnmount中解绑事件;
    • componentDidMount中进行数据的请求,而不是在componentWillMount
    • 需要根据 props 更新 state 时,使用getDerivedStateFromProps(nextProps, prevState)
      • 旧 props 需要自己存储,以便比较;
      • public static getDerivedStateFromProps(nextProps, prevState) {
        	// 当新 props 中的 data 发生变化时,同步更新到 state 上
        	if (nextProps.data !== prevState.data) {
        		return {
        			data: nextProps.data
        		}
        	} else {
        		return null1
        	}
        }
        

          

    • 可以在componentDidUpdate监听 props 或者 state 的变化,例如:
    componentDidUpdate(prevProps) {
    	// 当 id 发生变化时,重新获取数据
    	if (this.props.id !== prevProps.id) {
    		this.fetchData(this.props.id);
    	}
    }
    

     

    • componentDidUpdate使用setState时,必须加条件,否则将进入死循环;
    • getSnapshotBeforeUpdate(prevProps, prevState)可以在更新之前获取最新的渲染数据,它的调用是在 render 之后, update 之前;
    • shouldComponentUpdate: 默认每次调用setState,一定会最终走到 diff 阶段,但可以通过shouldComponentUpdate的生命钩子返回false来直接阻止后面的逻辑执行,通常是用于做条件渲染,优化渲染的性能。

    二: 虚拟DOM的理解

      (1)Virtual DOM是对DOM的抽象,本质上是JavaScript对象,这个对象就是更加轻量级的对DOM的描述.

        (2)两个内容的差异,进行dom的对比,事件属性方法,耗性能,dom对象转换为js对象,比较会快。有效提升性能。

      (3)首先,我们都知道在前端性能优化的一个秘诀就是尽可能少地操作DOM,不仅仅是DOM相对较慢,更因为频繁变动DOM会造成浏览器的回流或者重回,这些都是性能的杀手,因此我们需要这一层抽象,在patch过程中尽可能地一次性将差异更新到DOM中,这样保证了DOM不会出现性能很差的情况.

        (4)更好的跨平台,比如Node.js就没有DOM,如果想实现SSR(服务端渲染),那么一个方式就是借助Virtual DOM,因为Virtual DOM本身是JavaScript对象.

    三:diff算法

      (1)diff的目的就是比较新旧Virtual DOM Tree找出差异并更新.

      (2)一层节点发现有问题,不再往下比,直接放弃,n的平方降低为n

    • 把树形结构按照层级分解,只比较同级元素(层级比较)
    • 给列表结构的每个单元添加唯一的 key 属性,方便比较(列表添加key)
    • React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
    • 选择性子树渲染。开发人员可以重写shouldComponentUpdate 提高 diff 的性能

    四:key值的作用

      (1)如果key值相同,dom直接复用,不用再创建dom,直接这两个比,不用循环比

      (2)用新指针对应节点的key去旧数组寻找对应的节点,这里分三种情况,

          当没有对应的key,那么创建新的节点,

          如果有key并且是相同的节点,把新节点patch到旧节点,

          如果有key但是不是相同的节点,则创建新节点

    五:怎么理解HOC高阶组件

       接收一些函数,返回函数,组件进行包装,返回一个新的组件,很多地方都要用,有一点区别,共用的东西写在高阶组件中,通过传递额外参数,动态改变组件不同场景下使用的差异。

    六:redux中间件的原理

      action--store-reducer-props   action和store之间,沟通的桥梁dispatch,改装dispatch,

      store.dispatch,直接把action(对象)传递给store,使用中间件,action可以是函数,可以将函数转换为对象,传递给store。

    七:setState发生了什么?遇到过什么坑

      调和的过程。setState一般怎么用,传递什么进去,对象还是方法。

    this.setState({
        name: '小李'
    });
    this.setState(() =>({
        name:'小李'
    }));
    永远用函数调用,会避免一些坑。
    this.setState({
        age: this.state.age+1
    });
    setState异步,疯狂点击按钮,age不是每次加1,会一次加5,6个,state异步,会进行累加
    <input  refs="input"  value={this.state.age} />  ====1 
    this.setState((prevState) =>{
        age: ++ prevState
    });
    this.refs.input.value  ==== 1
    this.setState((prevState) =>{
        age: ++ prevState
    }, () => {
        this.refs.input.value  // 异步执行完state之后执行
    });

    八:ref是一个函数,有什么好处?

      方便react在销毁组件重新渲染,有效清空ref引用中的东西,防止内存泄漏

    九:refs作用是什么,在什么场景下用过?

      操作dom(滚动条,点击按钮,滚动条滚动到上面)

      图片展示获取图片的宽和高,

    十:react中this的指向问题

      

    十一:react-router的实现原理

    hash/location

    十二:jsx代码的转化(babel)

    createElement

    十三:受控组件和非受控组件

    受控:有生命周期

    非受控:纯函数

    十四:函数组件怎么做性能优化

    十五:react-saga的设计思想

    改装dispatch   action-----store之间,action可以是一个函数,可以执行异步操作

    十六:组件是什么?类是什么?类被编译成什么?

    十七:reselect是做什么使用的?

    十八:什么时候使用异步组件?

    十九:xss攻击,react如何防范?

    二十:react怎么提高性能优化?

    shouldComponentUpdate

    pureComponent

    二十一:ssr

    二十二:

    • 为什么返回多个标签或组件必须要用一个标签或组件包裹?
    • 为什么在根本没有使用React这个变量的情况下还要import React

    整个UI实际上是通过层层嵌套的React.createElement方法返回的,所以我们要在文件开头import React,否则编译后就会发现createElement没有定义。

    React.createElement执行的结果是一个对象,对象的属性描述了标签或组件的性状,对象再嵌套子对象。如果顶层返回多个标签,就无法表达为一个对象了

  • 相关阅读:
    HTML标签
    Web标准
    Web服务器 (获取域名)
    网站favicon.ico 图标
    模块化
    外边距
    h5css产品模块设计
    用策略模式(自定义注解+包扫描)解决if else 太多的问题
    方法区 永久代 元空间 常量池
    javac jar java
  • 原文地址:https://www.cnblogs.com/jcxfighting/p/11681992.html
Copyright © 2011-2022 走看看