react 源码学习

1. React Api

  • Fiber: react 16 中引入,解决js单线程运行时,计算量太大导致的动画卡帧和交互卡顿的问题。
  • Flow Type: react中用到的类型检测。
  • jsx到javaScript的转变: createElement(type, config, children) (react.js文件) 接受三个参数,使用babel转变查看:babel
    在这里插入图片描述
    createElement需要注意几点:
  1. 标签转换是通过React的createElement方法实现,该方法接受三个参数:分别为dom类型,props属性,第三个参数及之后的都算作该标签的子节点。
  2. 原生标签显示为字符串,而自定义组件以大写字母开头,显示为变量。
  3. 其中createElement()方法中获取默认属性的方式: 如果定义了defaultProps,则会设置默认的props值。
 if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }
  1. 该方法返回ReactElement
const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    // This tag allows us to uniquely identify this as a React Element
    $$typeof: REACT_ELEMENT_TYPE,

    // Built-in properties that belong on the element
    type: type,
    key: key,
    ref: ref,
    props: props,

    // Record the component responsible for creating this element.
    _owner: owner,
  };
  return element;
}

其中需要注意 $$typeof 表示react的节点,通过createElement() 方法创建的都是react的节点。

  • Component和PureComponent:ReactBaseClasses.js 文件)
    PureComponent 继承自 Component,继承方法使用了很典型的寄生组合式。PureComponent通过prop和state的浅比较来实现shouldComponentUpdate,所以当PureComponent的组件中对象或数组的值改变单引用地址不变则不会更新数据。
Component.prototype.setState = function(partialState, callback) {
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};

eg: 当state中数组arr的值为['1'] 可以通过下面的拓展运算符在PureComponent中得到更新

  this.setState({
	  arr: [...arr, '2']
  })
	function ComponentDummy() {}
	ComponentDummy.prototype = Component.prototype;
	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;
  • render
    1. 在reactDOM.js 中render 返回 legacyRenderSubtreeIntoContainer() 函数
  render(
    element: React$Element<any>,
    container: DOMContainer,
    callback: ?Function,
  ) {
    invariant(
      isValidContainer(container),
      'Target container is not a DOM element.',
    );
    return legacyRenderSubtreeIntoContainer(
      null,
      element,
      container,
      false,  //  这个参数为 true 时表明了是服务端渲染, false 为客户端渲染
      callback,
    );
  },
  1. legacyRenderSubtreeIntoContainer 中 一部分是没有 root 之前我们首先需要创建一个 root,第二部分是有 root 之后的渲染流程。
    1⃣️ : 创建root节点
function legacyCreateRootFromDOMContainer(
  container: DOMContainer,
  forceHydrate: boolean,
): _ReactSyncRoot {
  const shouldHydrate =
    forceHydrate || shouldHydrateDueToLegacyHeuristic(container);
  // First clear any existing content.
  if (!shouldHydrate) {
    let warned = false;
    let rootSibling;
    while ((rootSibling = container.lastChild)) {
      container.removeChild(rootSibling);  // ** 容器内部不要含有任何的子节点。一是肯定会被移除掉,二来还要进行 DOM 操作,可能还会涉及到重绘回流等等。
    }
  }
  // Legacy roots are not batched.
  return new ReactSyncRoot(container, LegacyRoot, shouldHydrate);  // 创建了一个 FiberRoot 对像
}

创建了一个 FiberRoot 对象,并挂载到了 _internalRoot 上

function ReactSyncRoot(
  container: DOMContainer,
  tag: RootTag,
  hydrate: boolean,
) {
  // Tag is either LegacyRoot or Concurrent Root
  const root = createContainer(container, tag, hydrate);
  this._internalRoot = root;
}

function createContainer(
  containerInfo: Container,
  tag: RootTag,
  hydrate: boolean,
): OpaqueRoot {
  return createFiberRoot(containerInfo, tag, hydrate);
}

**content: ** 多用于多层父子组件关系传递信息。
ConcurrentMode : ConcurrentMode会降低包裹的子组件渲染的优先级。

2. React中的创建更新

React中对比一个ClassComponent是否需要更新: 只有两个地方。一是看有没有shouldComponentUpdate方法,二就是PureComponent判断
react中比较多的数据结构使用二进制: 为了简化类型比较,以及类型复合的方向

3. React调度过程(Fiber Scheduler)

什么是Fiber?
每一个ReactElement对应一个Fiber对象,记录节点的各种状态,串联整个应用形成树结构。
什么是update?
用于记录组件状态的改变。

4. 组件如何进行更新

5. 组件更新完成后进行的操作

1. 虚拟Dom对比

2. 渲染中出现错误的处理过程

6. 真实Dom更新

7. 各种功能的实现(content,ref,hydrate…)

8. Suspense (超前体验)

9. Hooks

### 回答1: 学习 React 源码是一项很有益的学习活动,可以帮助你加深对 React 的理解,并且为你提供有关如何实现组件化和声明式编程的知识。 在学习 React 源码时,我有几个建议: 1. 先从官方文档入手,了解 React 的基本概念和使用方法。这将有助于你更好地理解 React 源码。 2. 认真阅读源码注释。React源码非常详细,并且有很多注释,这些注释很有帮助,可以帮助你理解源码的目的和工作原理。 3. 使用调试工具,以帮助你更好地理解源码的工作流程。比如,可以使用浏览器的开发者工具调试 React 代码,或者使用断点调试。 4. 尝试实现一些自己的功能,并结合源码来调试和理解。这将有助于你更好地理解 React 的工作原理,并且能够让你在实际使用中更加熟练。 5. 可以尝试加入 React 开源社区,与其他 React 开发者交流经验,也可以参与 React 的开源项目,为 React 贡献代码。这将有助于你不断学习和提升。 ### 回答2: 学习React源码是一个非常有挑战性但也非常有价值的任务。首先,我建议你先熟悉React的基本概念和使用方法,理解React的核心思想和设计理念,然后再深入研究源码。以下是一些具体的建议: 1. 掌握JavaScript和ES6的基础知识:React源码是用JavaScript编写的,因此对于JavaScript的理解是必要的。确保你对JavaScript中ES6的新特性例如模块导入导出、箭头函数、解构赋值等有一定的了解。 2. 阅读官方文档和源码注释:React官方提供了非常详细的文档和源码注释,阅读它们可以帮助你快速了解React的内部工作原理和实现细节。 3. 从顶层开始分析:从React的顶层入手,逐步深入源码。首先阅读React的入口文件,了解React是如何初始化和渲染组件的。然后再深入了解React组件的生命周期和更新机制。 4. 使用工具进行调试:使用Chrome DevTools等工具进行调试可以帮助你更好地理解和分析React的运行时行为。通过在源码中设置断点并观察变量的值,可以深入理解React的执行流程。 5. 理解虚拟DOM和协调算法:React的核心是虚拟DOM和协调算法,学习和理解它们对于深入理解React源码非常重要。阅读相关的源码实现,将有助于你理解React如何高效地更新DOM。 6. 参考社区资源和开源项目:React有一个非常庞大的社区,许多优秀的开源项目可以帮助你更好地理解React源码。与其他人一起学习和讨论,参与到React相关的开源项目中,将加快你的学习进度。 总结起来,学习React源码需要坚实的JavaScript基础和对React的理解。通过仔细阅读官方文档、源码注释和调试工具的使用,以及参考社区资源和开源项目,你将能够逐渐深入了解React的实现细节,提高自己的技术水平。 ### 回答3: 学习React源码的过程可以相当艰巨,但也是丰富而值得的。以下是几些建议帮助你更好地学习React源码: 1. 先理解React的核心概念:在深入研究源码前,先确保你对React的基本理念和工作方式有了清晰的理解。了解虚拟DOM、组件生命周期、状态管理和数据流等核心概念将有助于更好地理解源码。 2. 创建一个简单的React应用:在学习React源码时,建议你尝试创建一个简单的React应用并深入研究它的实现细节。这样可以帮助你更好地理解React的工作原理和内部机制。 3. 阅读React官方文档和源码注释:React源码中有丰富的注释,它们会对源码的实现细节进行解释和说明。同时,React官方文档也提供了很多有价值的内容,包括API文档和设计原则。阅读这些内容能够帮助你更好地理解React的思想和设计理念。 4. 利用调试工具:学习源码的过程中,调试工具是非常有用的辅助资源。使用断点和调试器来观察源码的执行路径和状态变化,可以帮助你更好地理解代码的运行机制。 5. 参考优秀的源码解析和开源项目:很多开发者在学习React源码后,会产生一些优秀的博客文章、视频教程和开源项目,其中包含了他们对源码的解析和实践。阅读这些资源可以帮助你更好地理解React源码并从中获取灵感。 学习React源码需要耐心和持续努力,希望以上建议能够帮助你更好地进行这个过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值