react相关问题

什么是JSX?——浏览器是如何识别它的?

JSX是facebook普及的一种标记语言,通过babel/TSC等工具会编译为React.createElementfunction。所以在React每个组件中,虽然没有显式用到React,但都需要import React from 'react'

JSX是如何区分React Component和HTML元素的?

通过元素首字母的大小写,如果首字母大写,则认为是React组件,小写的话则会被认为是HTML元素。可以在online Babel compiler中试一下。

123456789101112
function () {  return <div>Hello world!</div>;}

function () {  return React.createElement(    "div",    null,    "Hello world!"  );}
123456789101112
function () {  return <div>Hello world!</div>;}

function () {  return React.createElement(    Div,    null,    "Hello world!"  );}

此外,把一个组件赋给this.component并且写<this.component />也会起作用。

react16生命周期

Mounting

  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount

子类必须在构造函数第一行执行super(props),否则我们无法在构造函数里拿到this对象,因为子类的实例要通过父类的构造函数完成塑造,得到与父类实例相同的属性和方法。es6的继承是先将是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))
不建议使用UNSAFE_componentWillMount(),因为它是在render之前执行,所以不会触发重新渲染。在该方法内调用setState会和constructor里的初始化state合并执行,应该放到constructor中去初始化。

Updating

  • static getDerivedStateFromProps(nextProps, prevState) //会返回一个对象来更新当前的state对象
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate(prevProps, prevState) 在dom更新前,可以保存之前的滚动位置,便于在componentDidUpdate中去恢复
  • componentDidUpdate(prevProps, prevState, snapshot) 在dom更新后,snapshot的值是getSnapshotBeforeUpdate的返回值

不建议使用UNSAFE_componentWillReceiveProps()UNSAFE_componentWillUpdate(),一次更新可能会调用多次。
UNSAFE_componentWillReceiveProps()经常会带来bug和不一致的问题,例如在该方法中设置input值,当父组件更新的时候,用户的输入就会被置空。

1234567891011121314151617
class EmailInput extends Component {  state = { email: this.props.email };

  render() {    return <input onChange={this.handleChange} value={this.state.email} />;  }

  handleChange = event => {    this.setState({ email: event.target.value });  };

  componentWillReceiveProps(nextProps) {    // This will erase any local state updates!    // Do not do this.    this.setState({ email: nextProps.email });  }}

Unmounting

  • componentWillUnmount()

getDerivedStateFromProps(props, state)每次render之前都会被触发,与componentWillReceiveProps只在父组件rerender时会触发不一样。此外,getDerivedStateFromProps方法不建议经常使用,使用前想一想是否有替代方案。

错误捕获

  • static getDerivedStateFromError(error)
  • componentDidCatch(error, info)
    错误边界(Error Boundaries) 仅可以捕获其子组件的错误。
    使用static getDerivedStateFromError()在抛出错误后渲染回退UI。 使用 componentDidCatch() 来记录错误信息。

异步加载

React V16.6引入的新特性lazy,以及React-loadable库。

getDerivedStateFromProps应用

加分题:数据获取为什么用 componentDidMount 而不是 constructor?

你希望听到的两个原因会是:“在渲染发生之前数据不会存在” —— 虽然不是主要原因,但它向您显示该人员了解组件的处理方式; “在 React Fiber 中使用新的异步渲染……” —— 有人一直在努力学习。

  • r1: SSR模式下,componentWillMount在server端也是会被调用的,内容返回到client端后,componentWillMount会被第二次调用,如果在componentWillMount中处理数据获取则会被调用两次。
  • r2: 在componentWillMount中调用setState不会触发rerender,所以一般不会被用来获取数据。
  • r3: React16之后采用了Fiber架构,类似ComponentWillMount的生命周期钩子都有可能执行多次,所以不在这些生命周期中做有副作用的操作,比如请求数据。
  • r4: constructor用来初始化组件,作用应该保持纯粹,不应该引入数据获取这种有副作用的操作。

react fiber纤程

fiber是纤程颗粒化的概念,一个线程可以包含多个Fiber,主要是对react更新机制的优化。React16之前的版本,更新组件会一直占用主线程,如果组件树过大,则可能会导致浏览器失去响应。在React16中加入的fiber可以将同步任务拆解,每次执行完一小片后,都会把控制权交还给react负责任务调度的模块,如果有优先级更高的任务,就先执行高优先级的任务。

大专栏  react相关问题headerlink" title="拆什么">拆什么

首先,看React的渲染,包括两个阶段:调度阶段(reconciliation)和渲染阶段(commit)。

  • 调度阶段react根据数据更新virtual DOM,再运用diff算法找到需要VDOM change。这一部分的工作是可以拆分的。
  • 渲染阶段根据计算出的所有diff去一次性更新真实的DOM。
    组件比较庞大时,diff运算会比较耗时,不可控,所以需要拆分的是调度阶段。
怎么拆

fiber tree的部分结构如下所示,将简单的数结构,变成了基于单链表的树结构。

12345678910
{    alternate: Fiber|null, //在fiber更新时克隆出的镜像fiber,对fiber的修改会标记在这个fiber上    nextEffect: Fiber | null, // 单链表结构,方便遍历 Fiber Tree 上有副作用的节点    pendingWorkPriority: PriorityLevel, // 标记子树上待更新任务的优先级

    stateNode: any, // 管理 instance 自身的特性    return: Fiber|null, // 指向 Fiber Tree 中的父节点    child: Fiber|null, // 指向第一个子节点    sibling: Fiber|null, // 指向兄弟节点}
执行顺序

因为是单链表(A → B → C)的结构,所以在每次执行到某个节点(A → B)被中断后,下次可以从该节点(B → C)接着执行。
requestIdleCallback会让一个低优先级的任务在空闲期被调用,而requestAnimationFrame会让一个高优先级的任务在下一个栈帧被调用,从而保证了主线程按照优先级执行 fiber 单元。

优先级顺序为:文本框输入 > 本次调度结束需完成的任务 > 动画过渡 > 交互反馈 > 数据更新 > 不会显示但以防将来会显示的任务。

因为react fiber机制,一个任务很可能执行到一半就被其他优先级更高的任务所替代,或者因为时间原因而被终止。当再次执行这个任务时,是从头开始执行一遍,就会导致组件的某些 will 生命周期可能被多次调用而影响性能。

REFs:

react事件注册分发

事件注册的时候,react 把所有事件都委托到了document上,减少注册事件的数量,降低内存占用。
事件被触发后,冒泡到document处,找到触发的dom和react component,当前触发的事件会被加入batchedUpdates批处理队列中,在事件对列中,事件分发的核心handleTopLevel保证了子元素在父元素前面(此处分析的是trapBubbledEvent)。
事件执行的时候,首先找到合适的plugin(v16版本有5种)构造对应的合成事件,第一次触发new 创建的事件对象会放到缓存池中,下次直接从对象池中取。最后,就是拿到与事件相关的元素实例和回调函数。

onClickCapture

如果想要注册捕获事件,可以使用onClickCapture。但React的合成事件都是统一注册在document元素上的,且只有冒泡阶段,但合成事件会区分捕获和冒泡两种类型,来保证合成事件的执行顺序。此外,原生事件的执行都会早于合成事件的执行,因为合成事件都要等到事件冒泡到document上,才会执行。
执行顺序是:原生捕获事件 -> 原生事件冒泡 -> 合成事件捕获 -> 合成事件冒泡

react 源码

Component和PureComponent比较

React组件继承了Component或者PureComponent,这两个父类的定义在ReactBaseClasses.js中。

12345678910111213141516171819
function ComponentDummy() {}ComponentDummy.prototype = Component.prototype;

/** * Convenience component with default shallow equality check for sCU. */function PureComponent(props, context, updater) {  this.props = props;  this.context = context;  // If a component has string refs, we will assign a different object later.  this.refs = emptyObject;  this.updater = updater || ReactNoopUpdateQueue;}

const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());pureComponentPrototype.constructor = PureComponent;// Avoid an extra prototype jump for these methods.Object.assign(pureComponentPrototype, Component.prototype);pureComponentPrototype.isPureReactComponent = true;

从源码上看PureComponent继承了Component,新增了isPureReactComponent变量。
在shouldComponentUpdate函数中,可以看到如果isPureReactComponent为true,会shollow比较新旧props和state是否相等,都相等的话会返回false。而Component始终会返回true。

12345
if (type.prototype && type.prototype.isPureReactComponent) {  return (    !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)  );}

在使用PureComponent时要注意:

  1. 尽量不要在render函数中给子组件绑定新的函数,如下面

    1
    <ChildComponent onclick={() => this.handleClick()}/>

这样每次render都会创建一个新的函数,改变了子组件的props参数,使子组件重新渲染。

  1. 尽量不要在render方法内生成数据
    生成新的数据,例如新的list数组,也会带来不必要的重新渲染。

    1234
    let list = [xxx];...{list.map(item => (<LiItem value={item}/>))}<ChildComponent onclick={() => this.handleClick()}/>

因此相比于 Component ,PureComponent 有性能上的更大提升:

  • 减少了组件无意义的重渲染(当 state 和 props 没有发生变化时),当结合 immutable 数据时其优更为明显;
  • 隔离了父组件与子组件的状态变化;
  1. 若是数组和对象等引用类型,则要引用不同,才会渲染
  2. 如果prop和state每次都会变,那么PureComponent的效率还不如Component,因为你知道的,进行浅比较也是需要时间

key值的作用

  • 提高diff的效率
  • 避免就地复用

原文地址:https://www.cnblogs.com/liuzhongrong/p/12262810.html

时间: 2024-10-12 23:23:58

react相关问题的相关文章

react相关

react 简单入门 ant 蚂蚁金服react组件

REACT相关资料合集

===实例=== https://github.com/jesseskinner/react-webpack-demo ===UI组件库=== https://github.com/amazeui/amazeui-reactReact UI组件库 https://github.com/ant-design/ant-designReact 企业级的UI库 https://github.com/callemall/material-uiReact UI组件库 https://github.com/i

react相关知识点总结

1 JSX解析的问题 JSX其实是语法糖: 开发环境会将JSX编译成JS代码 react定义的方法,用来解析html,第一个参数是“html元素”,第二个参数是“属性”,第三个参数是其子元素: 所以下面的html会转成: 再如: 验证方式:使用babel的transfrom-react-jsx插件来转译react代码: 转译成: 此外,react是如何编译自定义的标签呢? 编译后: vDom是React初次推广开来的,结合了JSX使用 snabbdom中的h函数=====vue中的_c函数===

react相关面试题

React 的核心流程可以分为两个部分: reconciliation (调度算法,也可称为 render): // 调和 更新 state 与 props: 调用生命周期钩子: 生成 virtual dom: 这里应该称为 Fiber Tree 更为符合: 通过新旧 vdom 进行 diff 算法,获取 vdom change: 确定是否需要重新渲染 commit: 如需要,则操作 dom 节点更新: constructor ====> 初始化state componentWillMount

关于react相关想法

1. 关联更新 2. 不可预测 这两点我非常赞同,尤其是第一点,现在存在非常多的关联更新,很难管理,目前还没想到好的方式处理:第二点,其实是第一点的结果,由于关联太多导致不可预测,也就是解决了关联更新,也就解决了第二点的大部分: 关联更新这块,我觉得根源在于需求是逐步修改的,也就是说白了很多时候的实现是被需求逐步改的,而需求本身其实开始考虑的时候并不完全,个人认为需要通过状态机或者一个整体的uml图来表达整个系统架构,包括交互,而不是停留在代码层面,这样关联更新和不可预测就可以很好的解决:同时,

React 相关开发工具

Gulp:是一个NodeJs项目构建工具,高效易学:把一个开发中的项目构建成一个可以部署在服务器上的项目,压缩 整合 gulp.task('1',['2','3'],function(){});// 执行完1,执行2和3 1 gulp.task('sass',function(){ 2 gulp.src('./sass/**/*.scss') //读入文件内容 3 .pipe(sass().on('error',sass.logError)) //转换成css 4 .pipe(gulp.dest

使用React重构百度新闻webapp前端

http://wangfupeng.coding.me/share/2016/08/06/restruct-bdnews-webapp-by-react.html 声明 本文仅仅是对前几个月使用React重构百度新闻webapp项目的一个总结和思考,不会泄露任何项目代码(文章中的代码都是fis3或其他开源产品的配置代码,fis3是百度开源产品),因此“伸手党”可绕行. 现在2016年8月,web前端技术这几年变化太快,因此一些信息的时效性非常重要,还是把时间写上比较好. 项目介绍 百度新闻的 w

React.js终探(七)(完)

我们在前面介绍了组件的各种特性,这一节我们来说说多组件的情况. 在实际开发中,我们的组件难免会遇到有公共部分的情况,如果是个别情况还好,但如果数量比较多的话,那这时候,就需要公用了. 怎么公用呢? React为我们提供了它的方法. mixin:复用代码 可以把部分代码提出来公用.mixin是掺合混合的意思,即可以把一个对象的属性拷贝到另一个对象上. 使用mixin有两步: 定义一个mixin对象,即如 1 var EzLoggerMixin = { 2 log:function(){ 3 //s

试着用React写项目-利用styled-components解决样式问题

转载请注明出处:王亟亟的大牛之路 啰嗦之前先案例,会渐渐丰富前端的知识点 https://github.com/ddwhan0123/Useful-Open-Source-Android 昨天用webpack把我们的项目跑了起来,没看的可以看下,比较有条理性:http://blog.csdn.net/ddwhan0123/article/details/55095661 今天我们就要写react的内容了,首先先要用npm来下载相关需要的依赖库 分别是react和react-dom npm ins