React 源码解析之总览

栏目: 服务器 · 发布时间: 5年前

内容简介:排版本小书的 React 版本是先说下 React16 这个版本节点吧。React16 较之前的版本是核心上的一次重写(想想就疯狂),虽然之前 API 没有变化继续使用,但同时也增加了很多好用的功能(不然不是白瞎了么)。这也是首次引入

排版本小书的 React 版本是 V16.8.6

先说下 React16 这个版本节点吧。

React16 较之前的版本是核心上的一次重写(想想就疯狂),虽然之前 API 没有变化继续使用,但同时也增加了很多好用的功能(不然不是白瞎了么)。这也是首次引入 Fiber 概念,之后新的功能都是围绕 Fiber ,比如 AsyncModeProfiler 等。

说明:后面章节贴代码的部分,我都会删除原来英文注释,加上自己的理解,有问题的地方,还请在评论中指出(如果有评论的话,没有评论可以加我,有朋自远方来...)

V16.8.6 代码

看看截止目前为止,React 暴露出来的 API

// react-16.8.6/packages/react/index.js
'use strict';
const React = require('./src/React');
module.exports = React.default || React;

// react-16.8.6/packages/react/src/React.js
...

const React = {
  // packages/react/src/ReactChildren.js
  Children: {
    map,
    forEach,
    count,
    toArray,
    only,
  },

  // packages/react/src/ReactCreateRef.js
  createRef,
  // packages/react/src/ReactBaseClasses.js
  Component,
  PureComponent,

  // packages/react/src/ReactContext.js
  createContext,
  // packages/react/src/forwardRef.js
  forwardRef,
  lazy,
  memo,

  // packages/react/src/ReactHooks.js
  useCallback,
  useContext,
  useEffect,
  useImperativeHandle,
  useDebugValue,
  useLayoutEffect,
  useMemo,
  useReducer,
  useRef,
  useState,

  // packages/shared/ReactSymbols.js
  Fragment: REACT_FRAGMENT_TYPE,
  StrictMode: REACT_STRICT_MODE_TYPE,
  Suspense: REACT_SUSPENSE_TYPE,

  // packages/react/src/ReactElementValidator.js
  createElement: __DEV__ ? createElementWithValidation : createElement,
  cloneElement: __DEV__ ? cloneElementWithValidation : cloneElement,
  createFactory: __DEV__ ? createFactoryWithValidation : createFactory,
  isValidElement: isValidElement,

  // packages/shared/ReactVersion.js
  version: ReactVersion,

  // packages/shared/ReactSymbols.js
  unstable_ConcurrentMode: REACT_CONCURRENT_MODE_TYPE,
  unstable_Profiler: REACT_PROFILER_TYPE,

  // packages/react/src/ReactSharedInternals.js
  __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals,
};

...
复制代码

上面代码我们选择性的去解析,无需所有都要去了解(个人学习方法方式)。

先说 Children

这个对象提供了一些处理 props.children 方法, children 是一个类似数组但又不是数组的数据结构,对其进行处理时可用 React.Children 外挂方法。

createRef

ref 用法,不推荐使用 string ref 用法,比如 <div ref="divRef" /> 。那正确姿势是怎样的呢?请看

class App extends React.Component {
  constructor() {
    this.ref = React.createRef();
  }

  render() {
    return <div ref={this.ref} />
    // or
    return <div ref={node => this.ref = node} />
  }
}
复制代码

ComponentPureComponent

packages/react/src/ReactBaseClasses.js 代码

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

Component.prototype.isReactComponent = {};
Component.prototype.setState = function(partialState, callback) {}
Component.prototype.forceUpdate = function(callback) {}

// ComponentDummy => Component仿制品
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;

// PureComponent
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 };
复制代码

这两个类基本相同,唯一区别是 PureComponent 的原型上多了一个标识 isPureReactComponent

if (ComponentExample.prototype && ComponentExample.prototype.isPureReactComponent) {
  return (
    !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
  );
}
复制代码

这是检查组件是否需要更新的一个判断, ComponentExample 是你声明的继承自 ComponentPureComponent 的类,他会判断你是否继承自 PureComponent ,如果是的话就用 shallowEqual 比较 stateprops

By the way(顺便说一下,允许我骚一下):React 中对比一个 ClassComponent 是否需要更新,只有两个地方。

一是看有没有 shouldComponentUpdate 方法;二就是这里的 PureComponent 判断;

createContext

createContext 是官方定稿的 context 方案,在这之前我们一直在用的老的 context API ,也是 React 不推荐的 API 。Now(现在),新的 API 出来了,官方也已经确定在 17 大版本会把老 API 去除。

新 API 的使用方法

const { Provider, Consumer } = React.createContext('defaultValue');

const ProviderComp = props => (
  <Provider value='realValue'>
    {props.children}
  </Provider>
);

const ConsumerComp = () => (
  <Consumer>
    {value => <p>{value}</p>}
  </Consumer>
)
复制代码

具体差异,后面讲 context 环节会详细指出。

forwardRef

forwardRef 是用来解决 HOC 组件传递 ref 的问题的,所谓 HOC 就是 Higher Order Component 。就拿 redux 来说,使用 connect 来给组件绑定需要的 state ,这其中其实就是给我们的组件在外部包了一层组件,然后通过 ...props 的方式把外部的 props 传入到实际组件。 forwardRef 的使用方法如下:

const TargetComponent = React.forwordRef((props, ref) => {
  <TargetComponent ref={ref} {...props} />
});
复制代码

这也说明了为什么要提供 createRef 作为新的 ref 使用方法的原因,如果用 string ref 就没法当作参数传递了。

后面章节会详细分析 ref

lazy

是用来实现异步加载模块的功能。

memo

是一个高阶函数,它与 React.PureComponent类似,但是一个函数组件而非一个类。

useXXX 系列

这就是 React16 的 Hooks 了,后续会做代码分解。

类型

Fragment: REACT_FRAGMENT_TYPE,
StrictMode: REACT_STRICT_MODE_TYPE,
Suspense: REACT_SUSPENSE_TYPE,
unstable_ConcurrentMode: REACT_CONCURRENT_MODE_TYPE,
unstable_Profiler: REACT_PROFILER_TYPE,
复制代码

这 5 个都是 React 提供的组件,但他们呢其实都只是 占位符 ,都是一个 Symbol ,在 React 实际检测到他们的时候会做一些特殊的处理,比如 StrictModeAsyncMode 会让他们的子节点对应的 Fiber 的 mode 都变成和他们一样的 mode

元素

createElement: __DEV__ ? createElementWithValidation : createElement,
cloneElement: __DEV__ ? cloneElementWithValidation : cloneElement,
createFactory: __DEV__ ? createFactoryWithValidation : createFactory,
isValidElement: isValidElement,
复制代码

createElement

是 React 输出中最重要的 API 了,是用来创建 ReactElement 的,但是很多前端童鞋却从没见过,也没用过,这是为什么呢?这就得感谢 JSX 了,我们知道 JSX 并不是标准的 js,所以要经过编译才能变成可运行的 js,而编译之后, createElement 就出现了:

// jsx
<div id="app">content</div>

// js
React.createElement('div', { id: 'app' }, 'content')
复制代码

cloneElement

它就很明显了,是用来克隆一个 ReactElement

createFactory

它是用来创建专门用来创建某一类 ReactElement 的工厂的

export function createFactory(type) {
  const factory = createElement.bind(null, type);
  factory.type = type;
  return factory;
}
复制代码

其实就是绑定了第一个参数的 createElement ,一般我们用 JSX 进行编程的时候不会用到这个 API。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

UNIX编程艺术

UNIX编程艺术

Eric S. Raymond / 姜宏、何源、蔡晓俊 / 电子工业出版社 / 2006-2 / 59.00元

本书主要介绍了Unix系统领域中的设计和开发哲学、思想文化体系、原则与经验,由公认的Unix编程大师、开源运动领袖人物之一Eric S. Raymond倾力多年写作而成。包括Unix设计者在内的多位领域专家也为本书贡献了宝贵的内容。本书内容涉及社群文化、软件开发设计与实现,覆盖面广、内容深邃,完全展现了作者极其深厚的经验积累和领域智慧。一起来看看 《UNIX编程艺术》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具