react 源码

react 源码

  • React.js 文件
const React = {
  Children: {
    map,
    forEach,
    count,
    toArray,
    only
  },

  createRef,
  Component,
  PureComponent,

  createContext,
  forwardRef,
  lazy,
  memo,

  useCallback,
  useContext,
  useEffect,
  useImperativeHandle,
  useDebugValue,
  useLayoutEffect,
  useMemo,
  useReducer,
  useRef,
  useState,

  Fragment: REACT_FRAGMENT_TYPE,
  Profiler: REACT_PROFILER_TYPE,
  StrictMode: REACT_STRICT_MODE_TYPE,
  Suspense: REACT_SUSPENSE_TYPE,
  unstable_SuspenseList: REACT_SUSPENSE_LIST_TYPE,

  createElement: __DEV__ ? createElementWithValidation : createElement,
  cloneElement: __DEV__ ? cloneElementWithValidation : cloneElement,
  createFactory: __DEV__ ? createFactoryWithValidation : createFactory,
  isValidElement: isValidElement,

  version: ReactVersion,

  unstable_withSuspenseConfig: withSuspenseConfig,

  __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals
};

if (enableFlareAPI) {
  React.unstable_useResponder = useResponder;
  React.unstable_createResponder = createResponder;
}

if (enableFundamentalAPI) {
  React.unstable_createFundamental = createFundamental;
}

if (enableScopeAPI) {
  React.unstable_createScope = createScope;
}

//注意:有些API添加了特性标志。
//确保开源的稳定构建
//不要修改react对象以避免deopts。
//同样,我们不要在稳定的构建中公开它们的名称。

if (enableJSXTransformAPI) {
  if (__DEV__) {
    React.jsxDEV = jsxWithValidation;
    React.jsx = jsxWithValidationDynamic;
    React.jsxs = jsxWithValidationStatic;
  } else {
    React.jsx = jsx;
    // 我们可能希望在内部对jsxs进行特殊处理,以利用静态子级的优势。
    // 现在我们可以发布相同的prod函数
    React.jsxs = jsx;
  }
}
  • ReactBaseClasses.js
/**
 * 用于组件更新状态的基类帮助程序。
 */
function Component(props, context, updater) {
  this.props = props;
  this.context = context;
  // 如果组件具有字符串 refs,我们稍后将分配不同的对象
  this.refs = emptyObject;
  // 我们初始化默认的更新程序,但真实的更新程序会由渲染器注入
  this.updater = updater || ReactNoopUpdateQueue;
}

Component.prototype.isReactComponent = {};

// 1. setState 方法
Component.prototype.setState = function(partialState, callback) {
  // ...
  this.updater.enqueueSetState(this, partialState, callback, "setState");
};

// 2. forceUpdate 方法
Component.prototype.forceUpdate = function(callback) {
  this.updater.enqueueForceUpdate(this, callback, "forceUpdate");
};

// 3. 不推荐使用的 API 的弃用警告
// defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);

/**
 * 具有默认浅层相等检查的便利组件
 */
function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}

const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
// 避免这些方法的额外原型跳转.
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;

export { Component, PureComponent };
  • ReactNoopUpdateQueue.js
const didWarnStateUpdateForUnmountedComponent = {};
// 警告Noop
function warnNoop(publicInstance, callerName) {
  if (__DEV__) {
    // ...
    // 堆栈溢出报错
    warningWithoutStack(
      false,
      "Can't call %s on a component that is not yet mounted. " +
        "This is a no-op, but it might indicate a bug in your application. " +
        "Instead, assign to `this.state` directly or define a `state = {};` " +
        "class property with the desired state in the %s component.",
      callerName,
      componentName
    );
  }
}
// 这是更新队列抽象的 API
const ReactNoopUpdateQueue = {
  /**
   * 检查是否已经安装了此复合组件
   * @param {ReactClass} publicInstance 我们要测试的实例.
   * @return {boolean} True if mounted, false otherwise.
   */
  isMounted: function(publicInstance) {
    return false;
  },
  /**
   * 强制更新. 只有在确定在DOM事务中‘not’时才应该调用它
   * @param {ReactClass} publicInstance 应该重新渲染的实例
   * @param {?function} callback 组件更新之后调用.
   * @param {?string} callerName 公共API中调用函数的名称
   */
  enqueueForceUpdate: function(publicInstance, callback, callerName) {
    warnNoop(publicInstance, "forceUpdate");
  },
  /**
   * 取代所有的状态,始终使用 this.setState 来改变状态
   * 你应该将 this.state 视为不可变
   * 无法保证 this.state 会立即更新,因此在调用此方法后访问 this.state 可能会返回旧值。
   * @param {ReactClass} publicInstance (同上)
   * @param {object} completeState 下一个状态.
   * @param {?function} callback (同上)
   * @param {?string} callerName (同上)
   */
  enqueueReplaceState: function(
    publicInstance,
    completeState,
    callback,
    callerName
  ) {
    warnNoop(publicInstance, "replaceState");
  },
  /**
   * 设置状态的子集
   * @param {ReactClass} publicInstance (同上)
   * @param {object} partialState 下一个要与状态合并的部分状态
   * @param {?function} callback (同上)
   * @param {?string} Name (同上)
   */
  enqueueSetState: function(
    publicInstance,
    partialState,
    callback,
    callerName
  ) {
    warnNoop(publicInstance, "setState");
  }
};
export default ReactNoopUpdateQueue;
  • ReactElement.js
/**
 * 工厂函数创建一个 react 元素
 */
const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    // 这个标签允许我们将其唯一地标识为一个react元素
    $$typeof: REACT_ELEMENT_TYPE,

    // 属于元素的内置属性
    type: type,
    key: key,
    ref: ref,
    props: props,

    // 记录负责创建此元素的组件
    _owner: owner
  };

  if (__DEV__) {
    // 这个验证标志是可变的。
    // 我们把它放在外部的后存储设备上为了我们可以冻结整个object。
    // 一旦在常用的开发环境中实现这一点,就可以使用WeakMap替换他们
    element._store = {};

    // 为了使ReactElements更容易用于测试,我们设置这个验证标志不可枚举
    // (在可能的情况下,他应该包含我们运行测试的每个环境)
    Object.defineProperty(element._store, "validated", {
      configurable: false,
      enumerable: false,
      writable: true,
      value: false
    });
    // self and source are DEV only properties.
    Object.defineProperty(element, "_self", {
      configurable: false,
      enumerable: false,
      writable: false,
      value: self
    });
    // 两个元素创建在两个不同的地方为了测试目的应该被考虑为是相等的,因此我们从枚举中隐藏他们
    Object.defineProperty(element, "_source", {
      configurable: false,
      enumerable: false,
      writable: false,
      value: source
    });
    if (Object.freeze) {
      Object.freeze(element.props);
      Object.freeze(element);
    }
  }

  return element;
};

export function jsx(type, config, maybeKey) {
  let propName;

  // 提取保留名称
  const props = {};

  let key = null;
  let ref = null;

  // key 会被传递进 props中.
  // 如果key是显示声明的,这会导致潜在的问题 (例如. <div {...props} key="Hi" />,我们想要阻止 key 的传递,但是作为一个中间步骤,除了 <div {...props} key="Hi" /> 之外,我们将对所有内容使用 jsxDEV,因为我们也没有办法确认 key 是否显式声明为未定义。
  if (maybeKey !== undefined) {
    key = "" + maybeKey;
  }

  if (hasValidKey(config)) {
    key = "" + config.key;
  }

  if (hasValidRef(config)) {
    ref = config.ref;
  }

  // 剩余的属性被添加进新的 props 对象中
  for (propName in config) {
    if (
      hasOwnProperty.call(config, propName) &&
      !RESERVED_PROPS.hasOwnProperty(propName)
    ) {
      props[propName] = config[propName];
    }
  }

  // 解析默认的 props
  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }

  return ReactElement(
    type,
    key,
    ref,
    undefined,
    undefined,
    ReactCurrentOwner.current,
    props
  );
}
/**
 * 创建并返回一个给定类型的 React 元素
 */
export function createElement(type, config, children) {
  let propName;

  // 提取保留名称
  const props = {};

  let key = null;
  let ref = null;
  let self = null;
  let source = null;

  if (config != null) {
    if (hasValidRef(config)) {
      ref = config.ref;
    }
    if (hasValidKey(config)) {
      key = "" + config.key;
    }

    self = config.__self === undefined ? null : config.__self;
    source = config.__source === undefined ? null : config.__source;
    // Remaining properties are added to a new props object
    for (propName in config) {
      if (
        hasOwnProperty.call(config, propName) &&
        !RESERVED_PROPS.hasOwnProperty(propName)
      ) {
        props[propName] = config[propName];
      }
    }
  }

  // Children 可以是一个以上的参数,他们被转移到新分配的 props 对象上。
  const childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    if (__DEV__) {
      if (Object.freeze) {
        Object.freeze(childArray);
      }
    }
    props.children = childArray;
  }

  // Resolve default props
  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }
  if (__DEV__) {
    if (key || ref) {
      const displayName =
        typeof type === "function"
          ? type.displayName || type.name || "Unknown"
          : type;
      if (key) {
        defineKeyPropWarningGetter(props, displayName);
      }
      if (ref) {
        defineRefPropWarningGetter(props, displayName);
      }
    }
  }
  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props
  );
}
  • ReactHooks.js

https://github.com/facebook/react

dispatcher.useContext

dispatcher.useState

dispatcher.useRef

dispatcher..useEffect

dispatcher.useCallback

dispatcher.useResponder

react-dom 源码

  • index.js
export type DOMContainer =
  | (Element & {
      _reactRootContainer: ?_ReactRoot,
      _reactHasBeenPassedToCreateRootDEV: ?boolean,
    })
  | (Document & {
      _reactRootContainer: ?_ReactRoot,
      _reactHasBeenPassedToCreateRootDEV: ?boolean,
    });
// 判断提供的DOM节点是否是有效的节点元素
function isValidContainer(node) {
  return !!(
    node &&
    (node.nodeType === ELEMENT_NODE ||
      node.nodeType === DOCUMENT_NODE ||
      node.nodeType === DOCUMENT_FRAGMENT_NODE ||
      (node.nodeType === COMMENT_NODE &&
        node.nodeValue === ' react-mount-point-unstable '))
  );
}
const ReactDOM: Object = {
    ...,
    render(
        element: React$Element<any>,
        container: DOMContainer,
        callback: ?Function ) {
            // 有效性验证
            invariant(
                isValidContainer(container),
                'target container is not a DOM element'
            );
            // 堆栈警告
            warningWithoutStack();
            return legacyRenderSubtreeIntoContainer(
                null,
                element,
                container,
                true,
                callback
            )
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值