前言
最近项目做的比较多,担心思维定式,所以业余时间想学点不一样的。想着自己好久没有读React源码了,没准会有新的火花迸发出来。
不着急看源码,先来定一个阅读计划吧。
磨刀不误砍柴工,定好计划再开工。
卖个萌,233
本次计划制定如下:
- 两个月的学习周期;
- 三个阶段;
- 三个目标;
我并不打算把React全部源码看一遍,囫囵的看一遍意义明显不大。所以制定了一个短期的精读计划。
注:本次React源码学习的版本是基于v17。
三个阶段
织毛衣带给我的灵感,阅读计划分成三个阶段。
找线头
React源码很庞大,首先需要做的是挑出自己感兴趣部分去学习。
目前计划阅读的内容点包括生命周期、事件处理、Diff算法、Hook等。
团线团
织毛衣之前很重要的一部是团线团,一般情况同一种颜色会团成一个线团,方便后面使用。
整个阅读计划以周为时间维度,每一周总结学习到的知识点。
织图案
将总结的知识点分成不同的主题输出技术文章。
三个目标
- 搞懂内部机制;
- 提炼设计思维;
- 产出学习笔记;
王国维的人生三种境界:
"昨夜西风凋碧树。独上高楼,望尽天涯路。"此第一境也。
"衣带渐宽终不悔,为伊消得人憔悴。"此第二境也。
"众里寻他千百度,蓦然回首,那人却在灯火阑珊处。"此第三境也。
准备工作
正式进入学习计划之前,先来做点准备工作。
源码下载
本次学习的源码是通过React官网提供的git地址下载的。
React源码位置
在已经下载的react-17.0.2文件中,通过以下路径,便能找到想要阅读的源码文件
/packages/react/src
试读
在React源码的阅读过程中,总结实现原理和实现模式可以帮助我拓展开发思维。
比如我下面截取的React.createElement的代码
/**
* Create and return a new ReactElement of the given type.
* See https://reactjs.org/docs/react-api.html#createelement
*/
export function createElement(type, config, children) {
let propName;
// Reserved names are extracted
const props = {};
let key = null;
let ref = null;
let self = null;
let source = null;
if (config != null) {
if (hasValidRef(config)) {
ref = config.ref;
if (__DEV__) {
warnIfStringRefCannotBeAutoConverted(config);
}
}
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 can be more than one argument, and those are transferred onto
// the newly allocated props object.
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,
);
}
不难发现,React.createElement底层是基于ReactElement实现的,而ReactElement方法的采用的是工厂模式的设计模。
工厂模式的设计思想是通过一个工厂函数,快速批量地建立一系列相同的类,也可以用来创建对象、方法。因此通过代码搜索发现React.cloneElement同样是基于ReactElement方法实现的。
这不,一个简单的试读,就发现了一个设计模式的实际应用场景,我对接下来两个月的学习充满了期待。