阅读React源码初尝试(1)
1、目的
PS: 这句话必须要写,读了一些源码我发现,他们也只是普通的代码,不过他们考虑到性能/扩展/维护/可读/间接/优秀的逻辑和设计模式,我们应学习这些,当然也不要怕他们是洪水猛兽
- 之前好像写给如何读源码的,不过那次是简单方法论,这次我们不仅重新总结一下方法,并且
实践一下,简单读一读 React
2、方法论
1.问题驱动, 比如 React setState如何起作用的,更新过程是怎样的,React fiber 到底神奇在哪里?如何提升性能的?
2.最新的源码,不仅是思维升级,还是可读性升级,学习成本 🆙 🆙
3.结构,项目有哪些组成部分,为了达到最终的产出,要经过哪几步流程。这些流程里,业界主流的方案有哪几种
4.本地 g clone xxx 拿下来 并且跑起来 ,为了更好的跑起来,找到类似这样的文件 **Contribution Guide** 这个文件会告诉你哪里可以进行预览你的更改
5.在自己想了解的地方 打## debugger && log 然后 想办法 打出自己的 log
6.关注官网动态和核心开发者动态
- 结构更多解释来源于 蚂蚁团队 请放心参考
比如前端 View 层框架,要渲染出 UI,组件要经过 mount、 render 等等步骤。数据驱动的前端框架,
在 mounted 之后,就会进入一个循环,当用户交互触发组件数据变化时,会更新 UI。其中数据的检测方式
又有分 Push 和 Pull 两种方案。渲染 UI 可以是全量的字符串模板替换,也可以是基于 Virtual DOM 的
差量 DOM 更新。
又比如前端的一些工具,Webpack 和 Babel 这些工具都是基于插件的。基本的工作流程就是读取文件,
解析代码成 AST,调用插件去转换 AST,最后生成代码。要了解 Webpack 的原理,就要知道 Webpack 基于
一个叫 [tapable](https://link.zhihu.com/?target=https%3A//github.com/webpack/tapable) 的模块系统
- 项目结构 更多 解释
需要找到 package / src / bin / lib 下的 核心文件部分
- 比如 React
3、实践 以 React setState 为例 看看发生了什么
- 前提
- React Core 包含了 React 的类定义和一些顶级 API。大部分的渲染和 View 层 diff 的逻辑都在 Reconciler 和 Renderer 中
步骤总结
1、 找到setState 相关内容
2、setState的入口文件在src/isomorphic/modern/class/ReactBaseClasses.js
- 此处 挂在 原型链上
Component.prototype.setState = function(partialState, callback) {
if (
typeof partialState !== 'object' &&
typeof partialState !== 'function' &&
partialState != null
) {
throw new Error(
'setState(...): takes an object of state variables to update or a ' +
'function which returns an object of state variables.',
);
}
debugger
this.updater.enqueueSetState(this, partialState, callback, 'setState');
};
- 在看这个
入口方法
enqueueSetState 定义 在此处 ReactNoopUpdateQueue.js
function enqueueUpdate(component) {
ensureInjected();
if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
dirtyComponents.push(component);
if (component._updateBatchNumber == null) {
component._updateBatchNumber = updateBatchNumber + 1;
}
}
if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
dirtyComponents.push(component);
判断batchingStrategy.isBatchingUpdates batchingStrategy是批量更新策略,isBatchingUpdates表示是否处于批量更新过程,开始默认值为false
3、事务流 batchedUpdates => 调用transaction
var ReactDefaultBatchingStrategy = {
isBatchingUpdates: false,
batchedUpdates: function(callback, a, b, c, d, e) {
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
ReactDefaultBatchingStrategy.isBatchingUpdates = true;
if (alreadyBatchingUpdates) {
return callback(a, b, c, d, e);
} else {
return transaction.perform(callback, null, a, b, c, d, e);
}
},
};
module.exports = ReactDefaultBatchingStrategy;
当isBatchingUpdates为true,处于更新事务状态中,则将Component存入dirtyComponent中, 否则调用batchedUpdates处理,发起一个transaction.perform()
4、 batchingStrategy 批量更新策略
var ReactDefaultBatchingStrategy = {
isBatchingUpdates: false,
batchedUpdates: function(callback, a, b, c, d, e) {
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
ReactDefaultBatchingStrategy.isBatchingUpdates = true;
if (alreadyBatchingUpdates) {
return callback(a, b, c, d, e);
} else {
return transaction.perform(callback, null, a, b, c, d, e);
}
},
};
- 非常明显isBatchingUpdates的初始值是false的,在调用batchedUpdates方法的时候会将isBatchingUpdates变量设置为true
4、小结
- 这是一个 小的切入点,但有了方法和例子,之后的阅读源码将通畅很多,大伙儿 可以赶快试试,有问题可以和我沟通,感谢支持,感谢👍
Last 参考文档
1.蚂蚁技术团队
转载自:https://juejin.cn/post/7142397447095091213