洞悉细节!react 16.8.6源码分析-2 组件构造与获取调用栈

本文是React 16.8.6源码分析系列的第二部分,主要探讨组件构造函数、PureComponent、组件调用堆栈以及hooks的实现。内容涵盖component和PureComponent的定义、createRef和React Debug模式下的组件调用堆栈详情,以及元素名称获取和属性保留字验证等关键点。
摘要由CSDN通过智能技术生成

前言

作为一个前端页面仔和需求粉碎机,在日常的工作中重复雷同的业务需求,能够获得的提高是很有限的。要想跳出此山中,开阔新视野,笔者墙裂建议大家阅读市面上顶尖开源库的源码。这是学习和掌握js语言特性的绝佳机会(前端发展到现在,大型应用高度依赖框架,正常情况下普通开发者是没有机会接触底层的语言特性),同时也是深刻理解框架底层思维的契机。这里笔者选择react第一个开刀,市面上不少关于react源码分析的文章要么过于老旧,要么只截取部分代码或者是伪代码,笔者这里将选取react的16.8.6版本作为示例,从第0行开始,不漏过任何一个源码细节,和大家分享笔者在源码阅读过程中的体会。希望和大家共同进步,本系列博文中涉及的源码本人会放在git仓库中,链接在文末。

正文

在这一篇中,我们将聚焦react虚拟DOM实现的核心,component的定义。

  1. component和PureComponent定义
/**
 * Base class helpers for the updating state of a component.
 */
//  组件的构造函数
function Component(props, context, updater) {
   
  this.props = props;
  this.context = context;
  //  如果组件使用字符串的refs,我们将会指定一个不同的对象
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  //  初始化默认的更新器,真实的更新器将会在渲染器内注入
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  this.updater = updater || ReactNoopUpdateQueue;
}

//  定义原型属性
Component.prototype.isReactComponent = {
   };

//  设置状态的子集,始终使用this去改变状态,需要把this.sate当成正常状态下不可变的
//  并不保证this.state会马上更新,先设置再取值可能返回的是老值
//  并不保证setState的调用是同步的,因为多个调用最终会被合并,你可以提供一个可选的回调,在setStates事实上完成之后调用
//  当一个函数传递给setState时,它将在未来的某个时间点被调用,并且使用最新的参数(state,props,context等)这心值可能跟this.xxx不一样
//  因为你的函数是在receiveProps之后,shouldComponentUpdate之前调用的,在这个新阶段,props和context并没有赋值给this
/**
 * Sets a subset of the state. Always use this to mutate
 * state. You should treat `this.state` as immutable.
 *
 * There is no guarantee that `this.state` will be immediately updated, so
 * accessing `this.state` after calling this method may return the old value.
 *
 * There is no guarantee that calls to `setState` will run synchronously,
 * as they may eventually be batched together.  You can provide an optional
 * callback that will be executed when the call to setState is actually
 * completed.
 *
 * When a function is provided to setState, it will be called at some point in
 * the future (not synchronously). It will be called with the up to date
 * component arguments (state, props, context). These values can be different
 * from this.* because your function may be called after receiveProps but before
 * shouldComponentUpdate, and this new state, props, and context will not yet be
 * assigned to this.
 *
 * @param {object|function} partialState Next partial state or function to
 *        produce next partial state to be merged with current state.
 * @param {?function} callback Called after state is updated.
 * @final
 * @protected
 */
Component.prototype.setState = function (partialState, callback) {
   
  //  void 0 === undefined 省字节,同时防止undefined被注入
  //  partialState需要是对象,函数或者null
  !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : void 0;
  //  进入队列状态更新
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};

//  强制刷新,该方法只能在非DOM转化态的时候调用
//  在一些深层状态改变但是setState没有被调用的时候使用,该方法不会调用shouldComponentUpdate,但componentWillUpdate和componentDidUpdate会被调用

/**
 * Forces an update. This should only be invoked when it is known with
 * certainty that we are **not** in a DOM transaction.
 *
 * You may want to call this when you know that some deeper aspect of the
 * component's state has changed but `setState` was not called.
 *
 * This will not invoke `shouldComponentUpdate`, but it will invoke
 * `componentWillUpdate` and `componentDidUpdate`.
 *
 * @param {?function} callback Called after update is complete.
 * @final
 * @protected
 */
Component.prototype.forceUpdate = function (callback) {
   
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};

//  废弃的api,这些api只会在经典的类组件上存在,我们将会遗弃它们。我们并不会直接移除他们,而是定义getter,并抛错
/**
 * Deprecated APIs. These APIs used to exist on classic React classes but since
 * we would like to deprecate them, we're not going to move them over to this
 * modern base class. Instead, we define a getter that warns if it's accessed.
 */
{
   
  var deprecatedAPIs = {
   
    isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],
    replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']
  };
  //  定义遗弃api的告警函数
  var defineDeprecationWarning = function (methodName, info) {
   
    Object.defineProperty(Component.prototype, methodName, {
   
      get: function () {
   
        lowPriorityWarning$1(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]);
        return undefined;
      }
    });
  };
  //  依次注入getter
  for (var fnName in deprecatedAPIs) {
   
    if (deprecatedAPIs.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值