说说 React组件开发中对于作用域的常见问题。

在 EMAScript5语法标准中,对于作用域的常见问题如下。
(1)在map等办法的回调函数中,要绑定作用域this(通过bind办法)。
(2)父组件传递给子组件办法的作用域是父组件实例化对象,无奈扭转。
(3)组件事件回调函数办法的作用域是组件实例化对象(绑定父组件提供的办法就是父组件实例化对象),无奈扭转。
在 EMAScript6语法标准中,对于作用域的常见问题如下。
(1)当应用箭头函数作为map等办法的回调函数时,箭头函数的作用域是以后组件的实例化对象(即箭头函数的作用域是定义时的作用域),毋庸绑定作用域。
(2)事件回调函数要绑定组件作用域。
(3)父组件传递办法要绑定父组件作用域。
总之,在 EMAScript6语法标准中,组件办法的作用域是能够扭转的。

什么是 React Fiber?

Fiber 是 React 16 中新的协调引擎或从新实现外围算法。它的次要指标是反对虚构DOM的增量渲染。React Fiber 的指标是进步其在动画、布局、手势、暂停、停止或重用等方面的适用性,并为不同类型的更新调配优先级,以及新的并发原语。
React Fiber 的指标是加强其在动画、布局和手势等畛域的适用性。它的次要个性是增量渲染:可能将渲染工作宰割成块,并将其扩散到多个帧中。

为什么浏览器无奈读取JSX?

浏览器只能解决 JavaScript 对象,而不能读取惯例 JavaScript 对象中的 JSX。所以为了使浏览器可能读取 JSX,首先,须要用像 Babel 这样的 JSX 转换器将 JSX 文件转换为 JavaScript 对象,而后再将其传给浏览器。

react中key的作用

简略的说:key 是虚构DOM中的一种标识,在更新显示是key起到了极其重要的作用

简单的说:当状态中的数据产生扭转的时候,react会依据【新数据】生成【新的虚构DOM】,随后react进行【新虚构DOM】 和 【旧的虚构DOM】的diff比拟,而在这个比拟过程中key就是起到是要害中用

在调用setState 之后产生了什么

  • 状态合并,触发和谐:

    setState函数之后,会将传入的参数对象与以后的状态合并,而后登程调用过程

  • 依据新的状态构建虚构dom树

    通过和谐过程,react会高效的依据新的状态构建虚构DOM树,筹备渲染整个UI页面

  • 计算新老树节点差别,最小化渲染

    得倒新的虚构DOM树后,会计算出新老树的节点差别,会依据差别对界面进行最小化渲染

  • 按需更新

    在差别话计算中,react能够绝对精确的晓得哪些地位产生了扭转以及该如何扭转,这保障按需更新,而不是发表从新渲染

React最新的⽣命周期是怎么的?

React 16之后有三个⽣命周期被废除(但并未删除)

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

官⽅打算在17版本齐全删除这三个函数,只保留UNSAVE_前缀的三个函数,⽬的是为了向下兼容,然而对于开发者⽽⾔应该尽量避免使⽤他们,⽽是使⽤新增的⽣命周期函数代替它们。

⽬前React16.8+的⽣命周期分为三个阶段,别离是挂载阶段、更新阶段、卸载阶段。

挂载阶段:

  • constructor:构造函数,最先被执⾏,咱们通常在构造函数⾥初始化state对象或者给⾃定义⽅法绑定this;
  • getDerivedStateFromProps:static getDerivedStateFromProps(nextProps, prevState),这是个动态⽅法,当咱们接管到新的属性想去批改咱们state, 能够使⽤getDerivedStateFromProps
  • render:render函数是纯函数,只返回须要渲染的东⻄,不应该蕴含其它的业务逻辑,能够返回原⽣的DOM、React组件、Fragment、Portals、字符串和数字、 Boolean和null等内容;
  • componentDidMount:组件装载之后调⽤,此时咱们能够获取到DOM节点并操作,⽐如对canvas,svg的操作,服务器申请,订阅都能够写在这个⾥⾯,然而记得在componentWillUnmount中勾销订阅;

更新阶段:

  • getDerivedStateFromProps: 此⽅法在更新个挂载阶段都可能会调⽤;
  • shouldComponentUpdate:shouldComponentUpdate(nextProps, nextState),有两个参数nextProps和nextState,示意新的属性和变动之后的state,返回⼀个布尔值,true示意会触发从新渲染,false示意不会触发从新渲染,默认返回true,咱们通常利⽤此⽣命周期来优化React程序性能;
  • render:更新阶段也会触发此⽣命周期;
  • getSnapshotBeforeUpdate:getSnapshotBeforeUpdate(prevProps, prevState),这个⽅法在render之后,componentDidUpdate之前调⽤,有两个参数prevProps和prevState,示意之前的属性和之前的state,这个函数有⼀个返回值,会作为第三个参数传给componentDidUpdate,如果你不想要返回值,能够返回null,此⽣命周期必须与componentDidUpdate搭配使⽤;
  • componentDidUpdate:componentDidUpdate(prevProps, prevState, snapshot),该⽅法在getSnapshotBeforeUpdate⽅法之后被调⽤,有三个参数prevProps,prevState,snapshot,示意之前的props,之前的state,和snapshot。第三个参数是getSnapshotBeforeUpdate返回的,如果触发某些回调函数时须要⽤到DOM元素的状态,则将对⽐或计算的过程迁徙⾄getSnapshotBeforeUpdate,而后在componentDidUpdate中统⼀触发回调或更新状态。

卸载阶段:

-componentWillUnmount:当咱们的组件被卸载或者销毁了就会调⽤,咱们能够在这个函数⾥去革除⼀些定时器,勾销⽹络申请,清理⽆效的DOM元素等垃圾清理⼯作。

总结:

  • componentWillMount:在渲染之前执行,用于根组件中的 App 级配置;
  • componentDidMount:在第一次渲染之后执行,能够在这里做AJAX申请,DOM的操作或状态更新以及设置事件监听器;
  • componentWillReceiveProps:在初始化render的时候不会执行,它会在组件承受到新的状态(Props)时被触发,个别用于父组件状态更新时子组件的从新渲染
  • shouldComponentUpdate:确定是否更新组件。默认状况下,它返回true。如果确定在state或props更新后组件不须要在从新渲染,则能够返回false,这是一个进步性能的办法;
  • componentWillUpdate:在shouldComponentUpdate返回true确定要更新组件之前件之前执行;
  • componentDidUpdate:它次要用于更新DOM以响应props或state更改;
  • componentWillUnmount:它用于勾销任何的网络申请,或删除与组件关联的所有事件监听器。

参考 前端进阶面试题具体解答

什么是JSX

jsx 是 javascriptML的简写,是react应用的一种文件,它利用 JavaScript 的表现力和相似 HTML 的模板语法,这使得 HTML 文件非常容易了解。此文件能使利用十分牢靠,并可能进步其性能
jsx的语法规定

  • 定义虚构DOM的时候 不须要写引号
  • 标签中要混入js表达式的时候须要用 {}
  • 在jsx中写标签的类名的时候 用className 代替class
  • 内联款式的时候 ,须要style={{key:value}}
  • 标签必须要闭合
  • 标签首字母的约定

    若为小写字母,则将jsx转换为html中同名元素,若html中无该标签明对应的同名元素 则报错

    若为大写字母,react就去渲染对应的组件,若没有定义组件 则报错

  • 当依据数据遍历生成的标签,肯定要给标签设置独自的key 否则会报错

在 ReactNative中,如何解决 adb devices找不到连贯设施的问题?

在应用 Genymotion时,首先须要在SDK的 platform-tools中退出环境变量,而后在 Genymotion中单击 Setting,抉择ADB选项卡,单击 Use custom Android SDK tools,浏览本地SDK的地位,单击OK按钮就能够了。启动虛拟机后,在cmd中输出 adb devices能够查看设施。

react性能优化计划

  • 重写shouldComponentUpdate来防止不必要的dom操作
  • 应用 production 版本的react.js
  • 应用key来帮忙React辨认列表中所有子组件的最小变动

React怎么做数据的检查和变动

Model扭转之后(可能是调用了setState),触发了virtual dom的更新,再用diff算法来把virtual DOM比拟real DOM,看看是哪个dom节点更新了,再渲染real dom

redux与mobx的区别?

两者对⽐:

  • redux将数据保留在单⼀的store中,mobx将数据保留在扩散的多个store中
  • redux使⽤plain object保留数据,须要⼿动解决变动后的操作;mobx适⽤observable保留数据,数据变动后⾃动解决响应的操作
  • redux使⽤不可变状态,这意味着状态是只读的,不能间接去批改它,⽽是应该返回⼀个新的状态,同时使⽤纯函数;mobx中的状态是可变的,能够间接对其进⾏批改

mobx相对来说⽐较简略,在其中有很多的形象,mobx更多的使⽤⾯向对象的编程思维;redux会⽐较简单,因为其中的函数式编程思维把握起来不是那么容易,同时须要借助⼀系列的中间件来解决异步和副作⽤

  • mobx中有更多的形象和封装,调试会⽐较艰难,同时后果也难以预测;⽽redux提供可能进⾏工夫回溯的开发⼯具,同时其纯函数以及更少的形象,让调试变得更加的容易

场景辨析:

  • 基于以上区别,咱们能够简略得剖析⼀下两者的不同使⽤场景。
  • mobx更适宜数据不简单的应⽤:mobx难以调试,很多状态⽆法回溯,⾯对复杂度⾼的应⽤时,往往⼒不从⼼。
  • redux适宜有回溯需要的应⽤:⽐如⼀个画板应⽤、⼀个表格应⽤,很多时候须要撤销、重做等操作,因为redux不可变的个性,人造⽀持这些操作。
  • mobx适宜短平快的项⽬:mobx上⼿简略,样板代码少,能够很⼤水平上提⾼开发效率。
  • 当然mobx和redux也并不⼀定是⾮此即彼的关系,你也能够在项⽬中⽤redux作为全局状态治理,⽤mobx作为组件部分状态管理器来⽤。

你对【繁多数据源】有什么了解

redux应用 store将程序的整个状态存储在同一个中央,因而所有组件的状态都存储在 Store 中,并且它们从 Store 自身接管更新。繁多状态树能够更容易地跟踪随工夫的变动,并调试或检查程序

在 Reducer文件里,对于返回的后果,要留神哪些问题?

在 Reducer文件里,对于返回的后果,必须要应用 Object.assign ( )来复制一份新的 state,否则页面不会跟着数据刷新。

return Object.assign({}, state, {  type: action.type,  shouldNotPaint: true,});

哪些办法会触发 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>        <button onClick={() => this.setState(null)}>setState null</button>        <Child />      </React.Fragement>    );  }}
  • 父组件从新渲染

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

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

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

React 的解决 render 的根本思维模式是每次一有变动就会去从新渲染整个利用。在 Virtual DOM 没有呈现之前,最简略的办法就是间接调用 innerHTML。Virtual DOM厉害的中央并不是说它比间接操作 DOM 快,而是说不论数据怎么变,都会尽量以最小的代价去更新 DOM。React 将 render 函数返回的虚构 DOM 树与老的进行比拟,从而确定 DOM 要不要更新、怎么更新。当 DOM 树很大时,遍历两棵树进行各种比对还是相当耗性能的,特地是在顶层 setState 一个渺小的批改,默认会去遍历整棵树。只管 React 应用高度优化的 Diff 算法,然而这个过程依然会损耗性能.

redux 有什么毛病

  • 一个组件所须要的数据,必须由父组件传过来,而不能像 flux 中间接从 store 取
  • 当一个组件相干数据更新时,即便父组件不须要用到这个组件,父组件还是会从新 render,可能会有效率影响,或者须要写简单的 shouldComponentUpdate 进行判断

对React-Fiber的了解,它解决了什么问题?

React V15 在渲染时,会递归比对 VirtualDOM 树,找出须要变动的节点,而后同步更新它们, 零打碎敲。这个过程期间, React 会占据浏览器资源,这会导致用户触发的事件得不到响应,并且会导致掉帧,导致用户感觉到卡顿

为了给用户制作一种利用很快的“假象”,不能让一个工作长期霸占着资源。 能够将浏览器的渲染、布局、绘制、资源加载(例如 HTML 解析)、事件响应、脚本执行视作操作系统的“过程”,须要通过某些调度策略正当地调配 CPU 资源,从而进步浏览器的用户响应速率, 同时兼顾工作执行效率。

所以 React 通过Fiber 架构,让这个执行过程变成可被中断。“适时”地让出 CPU 执行权,除了能够让浏览器及时地响应用户的交互,还有其余益处:

  • 分批延时对DOM进行操作,防止一次性操作大量 DOM 节点,能够失去更好的用户体验;
  • 给浏览器一点喘息的机会,它会对代码进行编译优化(JIT)及进行热代码优化,或者对 reflow 进行修改。

核心思想: Fiber 也称协程或者纤程。它和线程并不一样,协程自身是没有并发或者并行能力的(须要配合线程),它只是一种管制流程的让出机制。让出 CPU 的执行权,让 CPU 能在这段时间执行其余的操作。渲染的过程能够被中断,能够将控制权交回浏览器,让位给高优先级的工作,浏览器闲暇后再复原渲染。

组件是什么?类是什么?类变编译成什么

  • 组件指的是页面的一部分,实质就是一个类,最实质就是一个构造函数
  • 类编译成构造函数

在React中如何防止不必要的render?

React 基于虚构 DOM 和高效 Diff 算法的完满配合,实现了对 DOM 最小粒度的更新。大多数状况下,React 对 DOM 的渲染效率足以业务日常。但在个别简单业务场景下,性能问题仍然会困扰咱们。此时须要采取一些措施来晋升运行性能,其很重要的一个方向,就是防止不必要的渲染(Render)。这里提下优化的点:

  • shouldComponentUpdate 和 PureComponent

在 React 类组件中,能够利用 shouldComponentUpdate或者 PureComponent 来缩小因父组件更新而触发子组件的 render,从而达到目标。shouldComponentUpdate 来决定是否组件是否从新渲染,如果不心愿组件从新渲染,返回 false 即可。

  • 利用高阶组件

在函数组件中,并没有 shouldComponentUpdate 这个生命周期,能够利用高阶组件,封装一个相似 PureComponet 的性能

  • 应用 React.memo

React.memo 是 React 16.6 新的一个 API,用来缓存组件的渲染,防止不必要的更新,其实也是一个高阶组件,与 PureComponent 非常相似,但不同的是, React.memo只能用于函数组件。

在React中组件的props扭转时更新组件的有哪些办法?

在一个组件传入的props更新时从新渲染该组件罕用的办法是在componentWillReceiveProps中将新的props更新到组件的state中(这种state被成为派生状态(Derived State)),从而实现从新渲染。React 16.3中还引入了一个新的钩子函数getDerivedStateFromProps来专门实现这一需要。

(1)componentWillReceiveProps(已废除)

在react的componentWillReceiveProps(nextProps)生命周期中,能够在子组件的render函数执行前,通过this.props获取旧的属性,通过nextProps获取新的props,比照两次props是否雷同,从而更新子组件本人的state。

这样的益处是,能够将数据申请放在这里进行执行,须要传的参数则从componentWillReceiveProps(nextProps)中获取。而不用将所有的申请都放在父组件中。于是该申请只会在该组件渲染时才会收回,从而加重申请累赘。

(2)getDerivedStateFromProps(16.3引入)

这个生命周期函数是为了代替componentWillReceiveProps存在的,所以在须要应用componentWillReceiveProps时,就能够思考应用getDerivedStateFromProps来进行代替。

两者的参数是不雷同的,而getDerivedStateFromProps是一个动态函数,也就是这个函数不能通过this拜访到class的属性,也并不举荐间接拜访属性。而是应该通过参数提供的nextProps以及prevState来进行判断,依据新传入的props来映射到state。

须要留神的是,如果props传入的内容不须要影响到你的state,那么就须要返回一个null,这个返回值是必须的,所以尽量将其写到函数的开端:

static getDerivedStateFromProps(nextProps, prevState) {    const {type} = nextProps;    // 当传入的type发生变化的时候,更新state    if (type !== prevState.type) {        return {            type,        };    }    // 否则,对于state不进行任何操作    return null;}

什么是state

  • 在组件初始化的时候 通过this.state 给组件设置一个初始化的state,第一次render的时候会用state来渲染组件
  • 通过this.setState办法来更新state