react源码_react源码结构 - CSDN
精华内容
参与话题
  • 初入React源码(一)

    2019-06-10 17:09:39
    React是我接触的第二个框架,我最初开始接触的是vue,但是并没有深入的理解过vue,然后在工作过程中,我开始使用了React,现在已经觉得React会比vue更加实用,但是这只是个人观点,可能只是我更喜欢React的写法吧,...

    导语

    React是我接触的第二个框架,我最初开始接触的是vue,但是并没有深入的理解过vue,然后在工作过程中,我开始使用了React,现在已经觉得React会比vue更加实用,但是这只是个人观点,可能只是我更喜欢React的写法吧,会给我一种代码界面比较清晰的感觉,所以我开始逐步的去准备了解这个玩意

    因为在这之前我只看过官方文档,所以我想按照React中JS存放的顺序,一个个去研究,可能会花费比较长的时间

    Index.js

    引入了React.js

    React.js

    它只做了一件事情,整合了所有我们开发中使用到的基础类以及方法,并export出React类。

    ReactBaseClasses.js

    这是我们常用的Component 以及 PureComponent的封装类。

    构造函数

    Component 的构造函数中,只申请私有的 prop , context , refs , updater 属性

    invariant 的方法库

    params:
    condition, format, a, b, c, d, e, f
    复制代码

    判断传入的condition的真实性,如果为假,即返回format中的错误信息

    在ReactBaseClasses中:

    component.prototype.setState函数中验证传入的是否为Object或者为function类型,由此可见,我们常用的setState是挂载在component的原型链上的

    那setState具体操作了啥呢?

    setState的时候最后调用了this.updater,而在构造函数中有这么一句话

    this.updater = updater || ReactNoopUpdateQueue;
    复制代码

    意思就是我们可以自定义自己的updater方法,如果不传入的话,会依托于React封装的 ReactNoopUpdateQueue 库,后续会自己介绍.

    再往下看下去,我们会看到这么一段话

    Component.prototype.forceUpdate = function(callback) {
      this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
    };
    复制代码

    说明,我们的 Component 中的 forceUpdate 实际上也是用 ReactNoopUpdateQueue 来进行封装的方法

    除了Component意外,同时还输出了PureComponent,基本结构一样,只是将Component原型链上的方法,直接赋予给PureComponent,减少了从原型链上查找的过程

    所以,从这方面说明, 使用PureComponent虽然效果跟Component一样,但是实际上少了一分查找的过程

    展开全文
  • react源码总览(翻译)

    2018-12-10 08:59:13
    react也有段时间了, 是时候看看人家源码了. 看源码之前看到官方文档 有这么篇文章介绍其代码结构了, 为了看源码能顺利些, 遂决定将其翻译来看看, 小弟英语也是半瓢水, 好多单词得查词典, 不当之处请批评. 直接从...

      用react也有段时间了, 是时候看看人家源码了. 看源码之前看到官方文档 有这么篇文章介绍其代码结构了, 为了看源码能顺利些, 遂决定将其翻译来看看, 小弟英语也是半瓢水, 好多单词得查词典, 不当之处请批评. 直接从字面翻译的, 后面看源码后可能会在再修改下.
      
      下面是翻译
      
      这部分将给你介绍下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 ==www.dasheng178.com= 4,
      
      'Math is not working today.'
      
      );
      
      当警告条件是false的时候会展示警告信息
      
      可以这么理解, 条件应该指示正常的情况, 而不是异常的情况. 就是说第一个参数是true表示的是正常, false是异常.
      
      最好避免使用console取代warnings.
      
      var warning = require(www.michenggw.com'warning');
      
      var didWarnAboutMath = false;
      
      if (!didWarnAboutMath) {
      
      warning(
      
      2 + 2 === 4,
      
      'Math is not working today.'
      
      );
      
      didWarnAboutMath =www.mhylpt.com 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 www.gcyL157.com= null;
      
      // Relies on dynamically injected value
      
      function createInstanceForText(text) {
      
      return new textComponentClass(www.mingcheng178.com text);
      
      }
      
      var ReactHostComponent www.yongshiyule178.com = {
      
      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

    展开全文
  • 源码分析是大多数开发者忽略的问题,然而想要在技术上有更深的造诣,源码分析必不可少! React 项目托管在 GitHub 项目开发指引也可见官网 How to Contribute 文章使用的版本为v16.8.6 开始 克隆代码到本地 git ...

    源码分析是大多数开发者忽略的问题,然而想要在技术上有更深的造诣,源码分析必不可少!

    React 项目托管在 GitHub
    项目开发指引也可见官网 How to Contribute
    文章使用的版本为v16.8.6

    开始

    克隆代码到本地

    git clone https://github.com/facebook/react.git
    

    在这里插入图片描述
    查看分支,git branch -a
    在这里插入图片描述
    切换到 16.8.6 分支,git checkout 16.8.6
    在这里插入图片描述
    安装依赖,yarn install

    由源码编译

    项目目录结构如图。
    在这里插入图片描述
    官网对编译的提示
    在这里插入图片描述
    从源码编译出 react.development.jsreact-dom.development.js
    执行

    yarn run build react/index, react-dom/index
    

    在这里插入图片描述
    构建出的文件,保存在 build/node_modules/react,有 commonjs 和 umd 两个版本。
    在这里插入图片描述
    直接打开 fixtures/packaging/babel-standalone/dev.html
    在这里插入图片描述
    页面使用的是最新编译出来的 react.development.js 和 react-dom.development.js
    在这里插入图片描述

    更改代码测试效果

    在 setState 内部添加一个 log,更改 packages/react/src/ReactBaseClasses.js
    在这里插入图片描述
    重新编译 react ,yarn run build react/index
    在这里插入图片描述
    查看 react.development.js,在 build/node_modules/react/umd/react.development.js
    在这里插入图片描述
    至此,代码编译都已经成功了。

    使用自己编译出来的 react、react-dom

    使用 create-react-app 初始化一个项目,删除 package.json 中 dependencies 中的 react、react-dom。
    在这里插入图片描述
    进入之前编译好的 react、react-dom 目录,分别执行 yarn link
    再到项目目录,输入yarn link react react-dom,启动 yarn start 即可。

    展开全文
  • 前几天有小伙伴和我聊天,谈到现在前端面试越来越难,动不动就是xxx原理,有没有看过xx源码之类的问题, 之后就问我应该怎么来学习现在主流框架的源码,于是有了这...React源码获取 在这里我选择用的的版本是16.10.0 ,

    前几天有小伙伴和我聊天,谈到现在前端面试越来越难,动不动就是xxx原理,有没有看过xx源码之类的问题, 之后就问我应该怎么来学习现在主流框架的源码,于是有了这一篇文章.

    说到使用react那很简单 react 和reactdom 两个文件引入一下就ok,但是这两个文件是经过编译打包,我们无法在里面进行断点调试或者console调试, 所以想学习框架源码,第一步就要在本地运行源码这样才能在内部进行各种输出调试。

    好了闲话不说,直接开始正题

    React源码获取

    在这里我选择用的的版本是16.10.0 , 获取方式当然是react的git仓库

    创建测试项目

    • 在本地通过create-react-app创建测试项目
    • 创建完项目之后要修改源码以及webopack配置,需要 将‘旺旺大礼包’给解出来 npm run eject
    • 项目目录下会多出一个config文件

     

     

    将创建的项目替换为下载的源码文件

    • 将下载16.10.0的项目源码丢到src目录下

     

     

    • 更改配置文件 ==/config/webpack.config.js== 在运行项目的时候编译我们导入的源码为
        resolve:{
            ...,
            alias: {
            // Support React Native Web
            // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
            // 'react-native': 'react-native-web',
            // Allows for better profiling with ReactDevTools
            // ...(isEnvProductionProfile && {
            //   'react-dom$': 'react-dom/profiling',
            //   'scheduler/tracing': 'scheduler/tracing-profiling',
            // }),
            // ...(modules.webpackAliases || {}),
            'react': path.resolve(__dirname, '../src/react/packages/react'),
            'react-dom': path.resolve(__dirname, '../src/react/packages/react-dom'),
            'legacy-events': path.resolve(__dirname, '../src/react/packages/legacy-events'),
            'shared': path.resolve(__dirname, '../src/react/packages/shared'),
            'react-reconciler': path.resolve(__dirname, '../src/react/packages/react-reconciler'),
          },
        }
    错误处理

    替换完成后,因为版本和编译的原因会遇到各种错误, 具体的错误类型与解决方式,在这里做一个简单的介绍

    flow 检测报错

     

     

    • 由于react的源码中采用了flow这个东东做类型检查, 所以我们需要安装 ==@babel/plugin-transform-flow-strip-types== 这个插件忽略类型检测
    • 插件安装
    npm install @babel/plugin-transform-flow-strip-types -D
    • 插件配置
       //在webpack.config.js的babel-loader中添加配置
        {
            test: /\.(js|mjs|jsx|ts|tsx)$/,
            include: paths.appSrc,
            loader: require.resolve('babel-loader'),
            options: {
            customize: require.resolve(
              'babel-preset-react-app/webpack-overrides'
            ),
        
            plugins: [
              ...,
              [require.resolve('@babel/plugin-transform-flow-strip-types')]
              // 配置忽略flow类型检测
            ],
            ...
        }

    HostConfig配置错误

     

     

    • 修改文件 ==src/react/packages/react-reconciler/src/ReactFiberHostConfig.js==, 根据环境去导出HostConfig。
    //添加以下代码 
    export * from './forks/ReactFiberHostConfig.dom';

    部分全局变量报错

     

     

    • 修改 ==/config/env.js== 中的stringifed对象增加属性
      const stringified = {
        'process.env': Object.keys(raw).reduce((env, key) => {
          env[key] = JSON.stringify(raw[key]);
          return env;
        }, {}),
        "__DEV__": true,
        "__PROFILE__": true,
        "__UMD__": true
      };

    hasOwnProperty ReactSharedInternals.js错误

     

     

    • 修改文件 ==src/react/packages/shared/ReactSharedInternals.js。==
    // react此时未export内容,直接从ReactSharedInternals拿值
    // import React from 'react';
    // 此时React为undefined
    // const ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
    ​
    import ReactSharedInternals from '../react/src/ReactSharedInternals';

    invariant() 函数报错

     

     

    • ==src/react/packages/shared/invariant.js== 文件下 invariant 函数的错误处理
    • 修改如下:
    export default function invariant(condition, format, a, b, c, d, e, f) {
      if(condition) return ;
      throw new Error(
        'Internal React error: invariant() is meant to be replaced at compile ' +
          'time. There is no runtime version.',
      );
    }
    ​

    到此为止现在运行的react项目采用的使我们下载导入的react16.10.0的源码,我们就可以在源码里进行输出的错误调试

    比如我在react/index.js源码 进行输出测试

    'use strict';
    ​
    const React = require('./src/React');
    console.log('源码测试',React)
    // TODO: decide on the top-level export form.
    // This is hacky but makes it work with both Rollup and Jest.
    module.exports = React.default || React;

     

     

    嫌弃本地测试环境配置太麻烦的话,各位小主可以直接从下面的地址拉取我配置好的开发项目

    https://github.com/fchangjun/ReactSourceCodeAnalyze.git

     

    展开全文
  • reactjs源码分析

    千次阅读 2015-09-16 00:31:04
    前端的发展特别快,经历过jQuery一统天下的工具库时代后,现在各种框架又开始百家争鸣了。angular,ember,backbone,vue,avalon,ploymer还有reactjs,作为一个前端真是稍不留神就感觉要被淘汰了,就在去年大家还...
  • javascript前端框架,react Facebook官方源码,通过查看源码分析react生命周期,每个钩子函数执行时机。
  • React 把组件看作状态机(有限状态机), 使用state来控制本地状态, 使用props来传递状态. 前面我们探讨了 React 如何映射状态到 UI 上(初始渲染), 那么接下来我们谈谈 React 时如何同步状态到 UI 上的, 也就是: React...
  • react系列源码完整版

    2020-07-30 23:30:19
    react源码,下载引入即可使用
  • React-从源码分析React Fiber工作原理

    千次阅读 2018-04-28 11:46:53
    本文的demo仓库在...为什么要重写React React16 以前 React16 以前,对virtural dom的更新和渲染是同步的。就是当一次更新或者一次加载开始以后,diff virtual dom并且渲染的过程是一口气完成的。如果组件...
  • React源码分析1 -- 框架

    万次阅读 2017-03-02 16:33:14
    1 源码结构我们分析的React源码version为16.0.0-alpha.3,源码目录如下图所示。含义如下 addons:插件,一些比较有用的工具,如transition动画 isomorphic: 同构,服务端在页面初次加载时,将所有方法渲染好,一次性...
  • React 后台管理系统项目

    千次阅读 2020-10-19 14:38:05
    react + redux + react-router + sass + antd + eslint + webpack 项目预览地址 https://jesonman.github.io/react-admin-demo/ 项目源码地址 https://github.com/JesonMan/react-admin/ 相关页面 登录 首...
  • React Sample Demo从无到有学习基础目录

    万次阅读 2019-07-03 17:21:16
    这里主要记录React相关学习过程中的目录,其中包括ES6语法和Webpack,最主要的是前端使用开源的UI来实现丰富复杂的界面 1.用户登陆界面(源码:这里) 2.数据用表格展示(源码:这里) 3.数据页面分页展示...
  • 二、JSX《第二章源码》 demo1 - 7 React使用原生Javascript版本 React使用JSX语句 React自动识别{},当javascript处理 React子节点this.props.children JSX中嵌入javascript;如:条件判断、使用变量、使用函数、...
  • react-router和react-router-dom的区别

    万次阅读 2018-06-19 20:04:39
    转载自:react-router和react-router-dom的区别react-router-v4,我称之为“第四代react-router”,react-router和react-router-dom的区别是什么呢?为什么有时候我们看到如下的写法:写法1:import {Swtich, Route, ...
  • ReactNative Android和iOS的实现原理

    千次阅读 2016-06-12 14:44:04
    今天想研究下ReactNative Android和iOS的实现原理,发现已经有人已经分析过源码了,2篇文章都是近期写的,真好。不过后面我还是自己去看看源码吧。 iOS RN实现分析 React Native 从入门到源码分析-了解RN百态 ...
  • ReactOS一个类似Windows NT的内核,通过下载源代码进行编译,以及在VMware中运行编译完成的CD。
  • 22 个优质的 React 开源项目

    万次阅读 2016-07-16 14:39:46
    https://xituqu.com/201.html
  • 1.在上篇文章的基础上:React list数据显示(含源码)Demo,添加Pagination库的引用 import Pagination from 'rc-pagination'; import 'rc-pagination/assets/index.css'; 2.在<DetailList&...
  • React Native开发的仿美团小demo

    万次阅读 2016-01-04 16:04:53
    使用React Native开发的一个仿美团首页小demo, 源码:https://github.com/lookingstars/RNMeituan 运行说明: 首先需要安装好运行React Native的相关环境, 首先需要安装好运行React Native的相关环境, ...
  • antd+react-router-dom实现导航菜单切换

    万次阅读 2018-04-10 22:13:11
    antd导航菜单用的是官网的Layout示例:点击打开链接和react-router-dom结合,实现点击不同菜单切换到不同页面。源码已经上传到git:点击打开链接
1 2 3 4 5 ... 20
收藏数 30,382
精华内容 12,152
关键字:

react源码