react相关面试题

React 的核心流程能够分为两个部分:javascript

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

    更新 state 与 props;java

    调用生命周期钩子;react

    生成 virtual dom;算法

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

    经过新旧 vdom 进行 diff 算法,获取 vdom change;数组

    肯定是否须要从新渲染浏览器

  commit:性能优化

    如须要,则操做 dom 节点更新;babel

 

 

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

在新版本中,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执行的结果是一个对象,对象的属性描述了标签或组件的性状,对象再嵌套子对象。若是顶层返回多个标签,就没法表达为一个对象了

相关文章
相关标签/搜索