乐趣区

React-源码阅读1027

React 源码阅读 1

Fork 最新版的 React 源码地址

React 入口

import ReactVersion from 'shared/ReactVersion';
import {
  REACT_FRAGMENT_TYPE,
  REACT_PROFILER_TYPE,
  REACT_STRICT_MODE_TYPE,
  REACT_SUSPENSE_TYPE,
  REACT_SUSPENSE_LIST_TYPE,
} from 'shared/ReactSymbols';

import {Component, PureComponent} from './ReactBaseClasses';
import {createRef} from './ReactCreateRef';
import {forEach, map, count, toArray, only} from './ReactChildren';
import {
  createElement,
  createFactory,
  cloneElement,
  isValidElement,
  jsx,
} from './ReactElement';
import {createContext} from './ReactContext';
import {lazy} from './ReactLazy';
import forwardRef from './forwardRef';
import memo from './memo';
import {
  useCallback,
  useContext,
  useEffect,
  useImperativeHandle,
  useDebugValue,
  useLayoutEffect,
  useMemo,
  useReducer,
  useRef,
  useState,
  useResponder,
} from './ReactHooks';
import {withSuspenseConfig} from './ReactBatchConfig';
import {
  createElementWithValidation,
  createFactoryWithValidation,
  cloneElementWithValidation,
  jsxWithValidation,
  jsxWithValidationStatic,
  jsxWithValidationDynamic,
} from './ReactElementValidator';
import ReactSharedInternals from './ReactSharedInternals';
import createFundamental from 'shared/createFundamentalComponent';
import createResponder from 'shared/createEventResponder';
import createScope from 'shared/createScope';
import {
  enableJSXTransformAPI,
  enableFlareAPI,
  enableFundamentalAPI,
  enableScopeAPI,
} from 'shared/ReactFeatureFlags';
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;}

// Note: some APIs are added with feature flags.
// Make sure that stable builds for open source
// don't modify the React object to avoid deopts.
// Also let's not expose their names in stable builds.

if (enableJSXTransformAPI) {if (__DEV__) {
    React.jsxDEV = jsxWithValidation;
    React.jsx = jsxWithValidationDynamic;
    React.jsxs = jsxWithValidationStatic;
  } else {
    React.jsx = jsx;
    // we may want to special case jsxs internally to take advantage of static children.
    // for now we can ship identical prod functions
    React.jsxs = jsx;
  }
}

export default React;

按照顺序一一对 React 进行解读:

Children

  Children: {
    map,
    forEach,
    count,
    toArray,
    only,
  },

React.Children 提供了用于处理 this.props.children 不透明数据结构的实用方法。

React.Children.map

children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg。如果 children 是一个数组,它将被遍历并为数组中的每个子节点调用该函数。
如果子节点为null 或是 undefined,则此方法将返回 null 或是 undefined,而不会返回数组。

如果 children 是一个 Fragment 对象,它将被视为单一子节点的情况处理,而不会被遍历。

  • Fragment 片段

http://react.html.cn/docs/fra…
https://getstream.io/blog/rea…

React 中一个常见模式是为一个组件返回多个元素。片段 (fragments) 可以让你将子元素列表添加到一个分组中,并且不会在DOM 中增加额外节点。
例如:

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

React.Children.forEach

React.Children.forEach(children, function[(thisArg)])

React.Children.map() 类似,但它不会返回一个数组。

React.Children.count

React.Children.count(children)

返回 children 中的组件总数量,等同于通过 mapforEach调用回调函数的次数。

React.Children.only

React.Children.only(children)

验证 children 是否只有一个子节点(一个 React 元素),如果有则返回它,否则此方法会抛出错误。

React.Children.only() 不接受 React.Children.map()的返回值,因为它是一个数组而并不是 React 元素。

React.Children.toArray

React.Children.toArray(children)

children 这个复杂的数据结构以数组的方式扁平展开并返回,并为每个子节点分配一个 key
当你想要在渲染函数中操作子节点的集合时,它会非常实用,特别是当你想要在向下传递 this.props.children 之前对内容重新排序或获取子集时。

React.Children.toArray() 在拉平展开子节点列表时,更改 key 值以保留嵌套数组的语义。
也就是说,toArray 会为返回数组中的每个 key添加前缀,以使得每个元素 key 的范围都限定在此函数入参数组的对象内。

具体理解可以看一下这篇文章对 React children 的深入理解

退出移动版