React 源碼閱讀-10_041

React 源碼閱讀-10

ReactBaseClasses

這個文件是export出了Component, PureComponent

export {Component, PureComponent};

源碼+註釋

/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

//生產環境使用,爲了拋出錯誤信息
import invariant from 'shared/invariant';

//只在開發環境有效,使用 console.warn(message);
import lowPriorityWarning from 'shared/lowPriorityWarning';

//沒有傳入參數updater參數時,this.updater的值就是ReactNoopUpdateQueue
//用於報警告的 可以忽略
import ReactNoopUpdateQueue from './ReactNoopUpdateQueue';

const emptyObject = {};
if (__DEV__) {
  Object.freeze(emptyObject);
  // Object.freeze() 方法可以凍結一個對象。一個被凍結的對象再也不能被修改;凍結了一個對象則不能向這個對象添加新的屬性,不能刪除已有屬性,不能修改該對象已有屬性的可枚舉性、可配置性、可寫性,以及不能修改已有屬性的值。此外,凍結一個對象後該對象的原型也不能被修改。freeze() 返回和傳入的參數相同的對象
}

/**
 * Base class helpers for the updating state of a component.
 */

// Base class用於更新組件的state。\
// Component()本質是一個類:

function Component(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  // 如果組件ref具有字符串引用,稍後將分配一個不同的對象
  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.state`會立即更新,因此
 *調用此方法後訪問`this.state`可能會返回舊值。
 *
 *不能保證對setState的調用將同步運行,
 *因爲它們最終可能會一起批處理。您可以提供可選
 *實際調用setState時將執行的回調
 *完成。
 *
 *將函數提供給setState時,它將在以下時間點被調用
 *未來(不同步)。它將被稱爲最新
 *組件參數(狀態,道具,上下文)。這些值可以不同
 *from this。*因爲您的函數可能在receiveProps之後但之前被調用
 *shouldComponentUpdate,這個新的狀態,道具和上下文還沒有
 *分配給這個
 *
 * @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) {
  invariant(
    typeof partialState === 'object' ||
      typeof partialState === 'function' ||
      partialState == null,
    'setState(...): takes an object of state variables to update or a ' +
      'function which returns an object of state variables.',
  );
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};

/**
強制更新。僅當已知時才應調用此方法
 *確定我們不是DOM事務中的**。
 *
 *如果您知道
 *組件的狀態已更改,但未調用`setState`。
 *
 *這不會調用`shouldComponentUpdate`,但是會調用
 *componentWillUpdate和componentDidUpdate。
 *
 * @param {?function} callback Called after update is complete.
 * @final
 * @protected
 */
Component.prototype.forceUpdate = function(callback) {
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};

/**
不推薦使用的API。這些API曾經存在於經典的React類上,但是由於
 *我們要棄用它們,我們不會將它們移至此
 *現代基層。取而代之的是,我們定義了一個getter,如果它被訪問,它會發出警告
 已經廢棄
 */
if (__DEV__) {
  const 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).',
    ],
  };
  const defineDeprecationWarning = function(methodName, info) {
    Object.defineProperty(Component.prototype, methodName, {
      get: function() {
        lowPriorityWarning(
          false,
          '%s(...) is deprecated in plain JavaScript React classes. %s',
          info[0],
          info[1],
        );
        return undefined;
      },
    });
  };
  for (const fnName in deprecatedAPIs) {
    if (deprecatedAPIs.hasOwnProperty(fnName)) {
      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
    }
  }
}

//虛擬組件
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;

// 帶有默認淺層相等性檢查的便利組件。
/**
 * Convenience component with default shallow equality check for sCU.
 */
// PureComponent最佳情況是展示組件
function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}

const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
// PureComponent.prototype等於ComponentDummy的實例 只繼承Component的原型,不包括constructor,以此來節省內存。
pureComponentPrototype.constructor = PureComponent;
// 原型的constructor等於自身,覆蓋掉Component.prototype的constructor(Component)
// Avoid an extra prototype jump for these methods.
// 對於這些方法,請避免額外的原型跳轉 爲了減少一次原型鏈查找
Object.assign(pureComponentPrototype, Component.prototype);

pureComponentPrototype.isPureReactComponent = true;

// PureComponent是自帶了一個簡單的shouldComponentUpdate來優化更新機制的

export {Component, PureComponent};
https://juejin.im/post/5b614d...

https://segmentfault.com/a/11...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章