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
中的组件总数量,等同于通过 map
或 forEach
调用回调函数的次数。
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 的深入理解