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 的深入理解