• 一天梳理完react面试题


    react和vue的区别

    相同点:

    1. 数据驱动页面,提供响应式的试图组件
    2. 都有virtual DOM,组件化的开发,通过props参数进行父子之间组件传递数据,都实现了webComponents规范
    3. 数据流动单向,都支持服务器的渲染SSR
    4. 都有支持native的方法,react有React native, vue有wexx

    不同点:

    1. 数据绑定:Vue实现了双向的数据绑定,react数据流动是单向的
    2. 数据渲染:大规模的数据渲染,react更快
    3. 使用场景:React配合Redux架构适合大规模多人协作复杂项目,Vue适合小快的项目
    4. 开发风格:react推荐做法jsx + inline style把html和css都写在js了

    vue是采用webpack +vue-loader单文件组件格式,html, js, css同一个文件

    哪些方法会触发 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中组件的this.state和setState有什么区别?

    this.state通常是用来初始化state的,this.setState是用来修改state值的。如果初始化了state之后再使用this.state,之前的state会被覆盖掉,如果使用this.setState,只会替换掉相应的state值。所以,如果想要修改state的值,就需要使用setState,而不能直接修改state,直接修改state之后页面是不会更新的。

    React的生命周期有哪些?

    React 通常将组件生命周期分为三个阶段:

    • 装载阶段(Mount),组件第一次在DOM树中被渲染的过程;
    • 更新过程(Update),组件状态发生变化,重新更新渲染的过程;
    • 卸载过程(Unmount),组件从DOM树中被移除的过程;
    1)组件挂载阶段

    挂载阶段组件被创建,然后组件实例插入到 DOM 中,完成组件的第一次渲染,该过程只会发生一次,在此阶段会依次调用以下这些方法:

    • constructor
    • getDerivedStateFromProps
    • render
    • componentDidMount
    (1)constructor

    组件的构造函数,第一个被执行,若没有显式定义它,会有一个默认的构造函数,但是若显式定义了构造函数,我们必须在构造函数中执行 super(props),否则无法在构造函数中拿到this。

    如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数Constructor。

    constructor中通常只做两件事:

    • 初始化组件的 state
    • 给事件处理方法绑定 this
    constructor(props) {
       
      super(props);
      // 不要在构造函数中调用 setState,可以直接给 state 设置初始值
      this.state = {
        counter: 0 }
      this.handleClick = this.handleClick.bind(this)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    (2)getDerivedStateFromProps
    static getDerivedStateFromProps(props, state)
    
    
    • 1
    • 2

    这是个静态方法,所以不能在这个函数里使用 this,有两个参数 props 和 state,分别指接收到的新参数和当前组件的 state 对象,这个函数会返回一个对象用来更新当前的 state 对象,如果不需要更新可以返回 null。

    该函数会在装载时,接收到新的 props 或者调用了 setState 和 forceUpdate 时被调用。如当接收到新的属性想修改 state ,就可以使用。

    // 当 props.counter 变化时,赋值给 state 
    class App extends React.Component {
       
      constructor(props) {
       
        super(props)
        this.state = {
       
          counter: 0
        }
      }
      static getDerivedStateFromProps(props, state) {
       
        if (props.counter !== state.counter) {
       
          return {
       
            counter: props.counter
          }
        }
        return null
      }
    
      handleClick = () => {
       
        this.setState({
       
          counter: this.state.counter + 1
        })
      }
      render() {
       
        return (
          <div>
            <h1 onClick={
       this.handleClick}>Hello, world!{
       this.state.counter}</h1>
          </div>
        )
      }
    }
    
    
    • 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
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    现在可以显式传入 counter ,但是这里有个问题,如果想要通过点击实现 state.counter 的增加,但这时会发现值不会发生任何变化,一直保持 props 传进来的值。这是由于在 React 16.4^ 的版本中 setState 和 forceUpdate 也会触发这个生命周期,所以当组件内部 state 变化后,就会重新走这个方法,同时会把 state 值赋值为 props 的值。因此需要多加一个字段来记录之前的 props 值,这样就会解决上述问题。具体如下:

    // 这里只列出需要变化的地方
    class App extends React.Component {
       
      constructor(props) {
       
        super(props)
        this.state = {
       
          // 增加一个 preCounter 来记录之前的 props 传来的值
          preCounter: 0,
          counter: 0
        }
      }
      static getDerivedStateFromProps(props, state) {
       
        // 跟 state.preCounter 进行比较
        if (props.counter !== state.preCounter) {
       
          return {
       
            counter: props.counter,
            preCounter: props.counter
          }
        }
        return null
      }
      handleClick = () => {
       
        this.setState({
       
          counter: this.state.counter + 1
        })
      
    • 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
    • 28
    • 29
    • 30
    • 31
    • 32
  • 相关阅读:
    k8s-svc外界访问pod容器服务-4
    docker使用Open Policy Agent(OPA)进行访问控制
    Facebook又双叒崩了!网友:扎克伯格一周只用上三天班?
    微服务系列一:微服务的优势与劣势
    JVM篇---第四篇
    [Micropython] esp8266 ------- led闪烁
    k8s最小镜像
    uniapp顶部状态栏设置(适配刘海屏)
    c++视觉处理---霍夫变换
    Python的21天学习总结
  • 原文地址:https://blog.csdn.net/beifeng11996/article/details/127840971