关于react.js:react源码解析5jsx核心api

react源码解析5.jsx&外围api

视频解说(高效学习):点击学习

课程目录:

1.开篇介绍和面试题

2.react的设计理念

3.react源码架构

4.源码目录构造和调试

5.jsx&外围api

6.legacy和concurrent模式入口函数

7.Fiber架构

8.render阶段

9.diff算法

10.commit阶段

11.生命周期

12.状态更新流程

13.hooks源码

14.手写hooks

15.scheduler&Lane

16.concurrent模式

17.context

18事件零碎

19.手写迷你版react

20.总结&第一章的面试题解答

21.demo

virtual Dom是什么

一句话概括就是,用js对象示意dom信息和构造,更新时从新渲染更新后的对象对应的dom,这个对象就是React.createElement()的返回后果

virtual Dom是一种编程形式,它以对象的模式保留在内存中,它形容了咱们dom的必要信息,并且用相似react-dom等模块与实在dom同步,这一过程也叫协调(reconciler),这种形式能够申明式的渲染相应的ui状态,让咱们从dom操作中解放出来,在react中是以fiber树的模式寄存组件树的相干信息,在更新时能够增量渲染相干dom,所以fiber也是virtual Dom实现的一部分

为什么要用virtual Dom

大量的dom操作慢,很小的更新都有可能引起页面的重新排列,js对象优于在内存中,解决起来更快,能够通过diff算法比拟新老virtual Dom的差别,并且批量、异步、最小化的执行dom的变更,以进步性能

另外就是能够跨平台,jsx –> ReactElement对象 –> 实在节点,有中间层的存在,就能够在操作实在节点之前进行对应的解决,解决的后果反映到实在节点上,这个实在节点能够是浏览器环境,也能够是Native环境

virtual Dom真的快吗?其实virtual Dom只是在更新的时候快,在利用初始的时候不肯定快

const div = document.createElement('div');
let str = ''
for(let k in div){
  str+=','+k
}
console.log(str)

jsx&createElement

jsx能够申明式的形容视图,晋升开发效率,通过babel能够转换成React.createElement()的语法糖,也是js语法的扩大。

jsx是ClassComponent的render函数或者FunctionComponent的返回值,能够用来示意组件的内容,在通过babel编译之后,最初会被编译成React.createElement,这就是为什么jsx文件要申明import React from 'react'的起因(react17之后不必导入),你能够在 babel编译jsx 站点查看jsx被编译后的后果

React.createElement的源码中做了如下几件事

  • 解决config,把除了保留属性外的其余config赋值给props
  • 把children解决后赋值给props.children
  • 解决defaultProps
  • 调用ReactElement返回一个jsx对象(virtual-dom)
//ReactElement.js
export function createElement(type, config, children) {
  let propName;

  const props = {};

  let key = null;
  let ref = null;
  let self = null;
  let source = null;

  if (config != null) {
    //解决config,把除了保留属性外的其余config赋值给props
    //...
  }

  const childrenLength = arguments.length - 2;
  //把children解决后赋值给props.children
  //...

  //解决defaultProps
  //...

  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );
}

const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    $$typeof: REACT_ELEMENT_TYPE,//示意是ReactElement类型

    type: type,//class或function
    key: key,//key
    ref: ref,//ref属性
    props: props,//props
    _owner: owner,
  };

  return element;
};

$$typeof示意的是组件的类型,例如在源码中有一个查看是否是非法Element的函数,就是根object.$$typeof === REACT_ELEMENT_TYPE来判断的

//ReactElement.js
export function isValidElement(object) {
  return (
    typeof object === 'object' &&
    object !== null &&
    object.$$typeof === REACT_ELEMENT_TYPE
  );
}

如果组件是ClassComponent则type是class自身,如果组件是FunctionComponent创立的,则type是这个function,源码中用ClassComponent.prototype.isReactComponent来区别二者。留神class或者function创立的组件肯定要首字母大写,不而后被当成一般节点,type就是字符串。

jsx对象上没有优先级、状态、effectTag等标记,这些标记在Fiber对象上,在mount时Fiber依据jsx对象来构建,在update时依据最新状态的jsx和current Fiber比照,造成新的workInProgress Fiber,最初workInProgress Fiber切换成current Fiber。

render

//ReactDOMLegacy.js
export function render(
  element: React$Element<any>,//jsx对象
  container: Container,//挂载dom
  callback: ?Function,//回调
) {
  
  return legacyRenderSubtreeIntoContainer(
    null,
    element,
    container,
    false,
    callback,
  );
}

能够看到render所做的事也就是调用legacyRenderSubtreeIntoContainer,这个函数在下一章解说,这里重点关注ReactDom.render()应用时候的三个参数。

component

//ReactBaseClasses.js
function Component(props, context, updater) {
  this.props = props;//props属性
  this.context = context;//以后的context
  this.refs = emptyObject;//ref挂载的对象
  this.updater = updater || ReactNoopUpdateQueue;//更新的对像
}

Component.prototype.isReactComponent = {};//示意是classComponent

component函数中次要在以后实例上挂载了props、context、refs、updater等,所以在组件的实例上能拿到这些,而更新次要的承载构造就是updater, 次要关注isReactComponent,它用来示意这个组件是类组件

总结:jsx是React.createElement的语法糖,jsx通过babel转化成React.createElement函数,React.createElement执行之后返回jsx对象,也叫virtual-dom,Fiber会依据jsx对象和current Fiber进行比照造成workInProgress Fiber

pureComponent也很简略,和component差不多,他会进行原型继承,而后赋值isPureReactComponent

function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}

const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;

export {Component, PureComponent};

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理