共计 4041 个字符,预计需要花费 11 分钟才能阅读完成。
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 的深入理解