react源码总览(翻译)

每次都信誓旦旦的给本身立下要好好进修react源码的flag,效果都是因为某个处所卡住了,或是其他缘由没看若干就摒弃了。此次又给本身立个flag-对峙看完react源码。为了催促本身,特开设如许一个专栏来纪录本身的进修进程,这意味着这个专栏的文章质量并不高,你能够拿来参考参考,切莫全信,我不想误人子弟,背面假如学有所成再斟酌产出些好点的文章。 假如发明文章中有什么不当之处,欢迎批评交换。我看的源码版本是
16.8.2

为了看react源码,我查找了不少材料,这里引荐两个参考材料,个人以为写得不错。

  1. 慕课网一个课的电子书,他有个源码剖析的视频教程,应当不错,不过我没买。
  2. 一个知乎专栏,写得很清楚,只不过是15.6.2的, 在react16内里一些要领找不到了。

本篇文章是官方文档里边的一篇文章的翻译,原文地点

这部份将给你引见下react代码的基础构造, 代码商定和它的基础完成.

假如你想为react孝敬代码的话, 我们愿望这篇指南能让你写代码越发惬意.

我们不引荐将这些商定用在react运用中, 因为这些商定大多是基于一些汗青缘由存在的, 跟着时候推移能够会发生变化.

外部依靠

react 几乎没有外部依靠. 一般require()指向的是react本身代码库的一个文件. 然则也有一些破例.

因为react想要经由过程库同享一些诸如Relay的小东西, 所以存在fbjs repository , 而且我们让他们是同步的. 我们没有依靠任何node生态体系下的小模块, 因为我们愿望facebook的工程师的能能再任何必要的时刻修正他们. fbjs中的任何东西都不能被以为是大众api, 而且他们只是为Facebook的一些工程运用, 比方react.

一级目次

克隆了react的堆栈后你会发明在里边有几个一级目次.

  • packages目次包含一些元数据(如package.json)和react库供应的一切包的源码(src的下面), 假如你想修正代码, src下面就是你要花时候最多的处所.
  • fixtures目次包含了为孝敬者预备的一些小的react的测试运用
  • build是react打包输出的目次. 他不在代码库治理领域, 然则当你第一次打包后就会天生.

文档是放在和react差别的另一个堆栈治理的.

另有一些其他一级目次, 他们大多是东西层面的, 在你孝敬代码时能够不会用到他们能.

配合测试(Colocated Tests)

我们没有搞个一级目次来做单元测试. 我们把它放在了被测试文件相邻的被称为__tests__的目次.

举个例子, 关于setInnerHTML.js这个文件的测试被放在与他同级的__tests__/setInnerHTML-test.js这个里边.

这个词不知道怎样翻译

Warnings and Invariants

react中运用warning模块显现正告信息.

var warning = require('warning');

warning(
  2 + 2 === 4,
  'Math is not working today.'
);

当正告前提是false的时刻会展示正告信息

能够这么明白, 前提应当指导一般的状况, 而不是非常的状况. 就是说第一个参数是true示意的是一般, false是非常.

最好防止运用console庖代warnings.

var warning = require('warning');

var didWarnAboutMath = false;
if (!didWarnAboutMath) {
  warning(
    2 + 2 === 4,
    'Math is not working today.'
  );
  didWarnAboutMath = true;
}

正告只会在开辟形式被开启. 临盆环境下被去掉了. 假如你想阻挠某些代码块的实行, 那末你能够用invariant模块.

var invariant = require('invariant');

invariant(
  2 + 2 === 4,
  'You shall not pass!'
);

当前提为false时, 这个要领会直接抛出非常.

“Invariant” 就是说这个前提为真, 你能够以为他就是做了个断言.

坚持开辟环境和临盆环境一致是很重要的, 因而invariant在临盆环境和开辟环境都能够抛出非常. 临盆环境下的毛病音讯被自动替换成毛病码, 以防增添代码体积.

Development and Production

你能够运用__DEV__这个为全局变量指定仅仅在开辟环境才实行的代码块.

他是在编译过程当中事情的, 他是在commonjs编译的时刻搜检process.env.NODE_ENV !== 'production'这个值.

零丁编译的时刻, 他在未压缩版是true, 在压缩版直接被去掉了.

if (__DEV__) {
  // 这里边的代码只会带开辟环境实行
}

Flow

我们近来最先引入flow做静态范例搜检, 在文件头的解释里标注了@flow的运用了范例搜检.

我们接收在现有代码到场flow范例搜检的pull request (不错哎, 能够试着提个pull request哦). Flow的署名类似下面如许.

ReactRef.detachRefs = function(
  instance: ReactInstance,
  element: ReactElement | string | number | null | false,
): void {
  // ...
}

时机成熟的时刻, 新代码要用Flow 署名, 你能够在当地运转yarn flow用Flow搜检你的代码.

动态植入

react在一些模块运用了动态植入. 然则这个东西不太好, 因为他让代码比较难明白了. 他存在的理由是react一最先只把支撑dom作为目的的. 然则厥后杀出了个React Native, 他是基于react的, 我们不能不到场动态植入好让react native 重载一些行动.

你能够会看到模块像下面如许声明它的动态依靠

// Dynamically injected
var textComponentClass = null;

// Relies on dynamically injected value
function createInstanceForText(text) {
  return new textComponentClass(text);
}

var ReactHostComponent = {
  createInstanceForText,

  // Provides an opportunity for dynamic injection
  injection: {
    injectTextComponentClass: function(componentClass) {
      textComponentClass = componentClass;
    },
  },
};

module.exports = ReactHostComponent;

注入的部份没有以任何体式格局特别处置惩罚. 然则划定, 它的意义是这个模块想在运转时有一些依靠(多是平台特定的)被注入进去.

代码里边有几个注入的进口. 将来, 我们将烧毁掉这类动态植入的机制, 计划是在编译时以静态体式格局处置惩罚他们.

多包

react是个monorepo, 他的堆栈包含了多个自力的包, 因而他们的修正能够合在一起, 而且issues也能够放在一个处所.

React中心

react的中心是一切顶级api, 包含:

  • React.createElement()
  • React.Component
  • React.Children

react中心只包含定义组件必要的api, 并不包含reconciliation算法和平台特定代码. React DOM和React Native都运用了他们.

react中心的相干代码在packages/react里边. npm运用时在react这个包里边, 浏览器版的是react.js, 他挂载一个被称为React的全局变量.

Renderers

react起初是为DOM制造的, 然则背景经由过程RN被用来支撑原生环境了. 这里引见加react内部的“renderers”的理念.

“renderers”治理了react树怎样变成平台可挪用的东西.

Renderers也在packages里边

  • React DOM Renderer 把react 组件衬着进 DOM. 他完成了顶级的ReactDOM APIs, 在react-dom这个npm包里被暴露出来. 浏览器版叫react-dom.js, 经由过程ReactDOM这个全局变量暴露出来.
  • React Native Renderer把react组件衬着到原生视图层里. 他被RN内部运用.
  • React Test Renderer 把react组件衬着成JSON树, 他被Jest的一个特征Snapshot Testing运用, 在react-test-renderer这个npm包里可用.

另一个官方唯一支撑的衬着器是react-art, 他曾经是个自力的库, 如今被移进来了.

注重

技术上
react-native-renderer是很薄的一层, 只是用来和RN的完成相互配合, 真正的平台相干代码是RN库里一些native view.

Reconcilers(谐和器)

相当多的衬着器, 如Reat DOM, React Native 须要同享一套逻辑. 特别reconciliation算法须要充足的类似, 以便让rendering, 自定义组件, 状况, 性命周期函数和refs能跨平台事情.

为了处理这个题目, 差别的衬着器共用一些代码. 我们把React 中的这个部份叫做”reconciler”. 当一个更新比方setState要实行了,Reconcilers就去在组件上挪用render(), 然后mounts, updates, 或许unmounts他们.

Reconcilers没有自力成包, 因为他如今还没有大众API. 相反, 他仅仅是在衬着器被运用, 比方React DOM , React Native.

Stack Reconciler

Stack Reconciler 是在react15之前完成运用的, 如今已不用了, 然则下一部份的文档还会有细致的引见.

Fiber Reconciler

“Fiber”是为了处理stack reconciler固有题目和修复长期存在的bug所做的勤奋, 他从react16最先成为默许的Reconciler.

他的重要目的是:

  • 在chunks里星散可中缀的事情
  • 在过程当中重修, 重用work或许转变他的优先级(瞎翻译的)的才能
  • 在父子组件行进或回退以只是react中的规划的才能
  • 在render要领里返回多个元素的才能
  • 更好的支撑毛病边际

你可在这里这里浏览更多关于Fiber架构的相干信息. 然则React16对他做了封装, 默许不支撑异步特征了.

他的源码在packages/react-reconciler里边.

事宜体系

react完成了一个对renders通明的事宜体系, 这个体系被用于react dom 和react native. 源码在packages/events;

这里有个视频https://www.youtube.com/watch?v=dRo_egw7tBc

    原文作者:Bigbear
    原文地址: https://segmentfault.com/a/1190000017315446
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞