前言
# 目录
这是 React 源码漂流记系列文章的第一篇。从今天开始,开启我们的 React 源码阅读之旅。
我阅读 React 的源码陆陆续续也有几个月之久,其间也有不少的收获和感悟,趁此机会,整理成文章,与大家分享和讨论,同时也可以给想要开始阅读源码的伙伴一些启发吧。
开始今天的内容之前,我想先聊几个问题,因为这是 React 源码阅读系列的第一篇文章,我想先分享一下我对阅读源码的一下见解。
# 前置知识
- 熟悉 Javascript 语言。
- 熟练使用 React 框架,并且有一定的开发经验。
# 为什么读 React 源码?
可能有如下的场景让你开始关注 React 源码:
- React 的使用已经得心应手了,迫切的想知道这些每天使用的 API 到底是什么原理?比如每天都用到 useState,那么究竟 useState 是如何处理组件的状态的呢?
- 需求开发中遇到奇怪的问题,怎么都找不到原因,是否是我对 API 的理解和使用有偏差?
- 业务太复杂,我的组件遇到了性能瓶颈,能榨干性能的手段悉数用尽,关于性能问题,是否还有其他的灵感呢?
- 我想写大型组件库,能够达到 antd 那样强大的功能,我需要对 React 以及更多更底层的 API 有更多的理解。
- 我想写框架玩玩,能否参照下 React 框架的思路?……
可能会遇到如下的问题,让你迫切的想要从 React 源码中找答案:
- 我的 setState 为什么没有更新组件的状态?为什么我的组件渲染了这么多次?这会不会很消耗性能?
- 为什么我需要给列表项设置 key 值,不设置 key 值会有什么问题?
- 为什么需要使用 useRef,为什么要使用 useMemo、useCallback 进行性能优化?这种优化是否是越多越好?
- 为什么 hook 只能在顶层使用,hook 为什么能够使业务逻辑得到复用?
- 为什么我的数据丢失了响应性,闭包问题又如何解决?……
不管你是为什么开始关注到 React 的原理,不管你是否开启了阅读 React 源码的计划,关注这个系列的文章,我们可以一起学习、成长与进步。
# 怎么读 React 源码?
我有如下的方法推荐给你:
- 断点调试,搜索脉络。通过简单的案例,从源码中打断点,逐步深入探索。好的搜索技巧可能帮助你快速找到你需要查看的函数。
- 由表及里,笔记加强。从 API 层,逐步向更深的实现逻辑追溯,直到形成知识的闭环。通过笔记记录自己的学习历程,不断更正和完善笔记内容。
- 问题驱动,寻找答案。从业务需求中遇到的问题出发,从源码中寻找答案,直到解决疑惑为止。
阅读源码的建议:
- 先关注核心逻辑,然后在关注实现细节。React 中有很多 Dev 环境、插件的代码或者是兼容性考虑的代码,可能会对你的阅读产生影响,可以跳过这些逻辑,只关注核心骨架。
- 分层阅读。React 内部分成了很多模块,可以根据阅读进度分层阅读,直到最终能够将各个模块的内容联动起来。
- 关注注释。源码中有很多详细的注释,关注注释可以给你更深的理解。
# 我们能从 React 源码中学习到什么?
- 对框架更深入的理解和掌握。
- 框架设计的思想和模式。
- js 的高级应用。
# 本系列的文章怎么解读 React 源码?
- 源码:源码本身是最重要的,文章中列出的源码都是已经提炼处理的核心的代码,去除了 dev 环境、各种插件或者非核心的代码,防止对您阅读产生影响。
- 篇幅:内容的篇幅不会很长,每篇文章会严格控制在 15 分钟阅读时间之内。如果您关注某些细节问题,可以参见【扩展】部分,这一部分会对本篇文章产生的若干细节问题进行扩展,当然如果您只关注骨干内容也可以跳过这一部分。
- 内容:源码的解读难以逃脱个人理解的范围,所以如果有错误的地方、或者您有不同的见解、更多的问题,还请及时指正或者在评论区提出。当然也有一些问题,会在【问题】部分列出,作为对文章内容的消化。
# 面试题热身
如果能够在面试的过程中畅谈 React 的设计原理,那必然能给面试官留下深刻的印象。不要怀疑这一点,在前端的学习过程中,除了经历所带来的的经验的知识广度之外,知识深度却并非任何人都能够达到的。在任何的专业领域,除了得见多识广,还必须得意见深刻方可。原理的学习就是这样一个 “见底” 和 “打磨” 的过程,这虽然是一趟孤独之旅,但终将使你受益颇深。
看源码本身就是跟专业的人、聪明的人对话的过程,虽然前期会觉得不知所云,但总有一天你也可以脱颖而出。关于 React 原理的面试题有很多经典的例子,大多是一些 “是什么” 的问题,关于这些问题我觉得你并不陌生,也没法难住你;然而本书的内容将要帮助你的,是解决 “为什么” 的问题。“为什么” 的问题才是最重要的问题,解决问题要从根上解决,看问题也需要从本质上去分析原因。下面列举一二,以供参考:
- 类组件与函数组件有什么区别?为什么有这些区别?
- 如何设计 React 组件?为什么?
- setState 是同步还是异步更新?为什么?
- Virtual DOM 的原理是什么?说说你对 React 中的 VDOM 的理解?
- 与其他框架相比,React 的 Diff 算法有何不同?有哪些利弊?
- 如何解释 React 的渲染流程?说说为什么采用这样的渲染流程?说说 React 的渲染方式与其他框架的异同?这样的渲染方式有何利弊?
- 如何分析和调优性能瓶颈?优化的原理是什么?
- React Hook 的使用限制有哪些?为什么?
- useEffect 和 useLayoutEffect 区别在哪里?为什么会有这样的区别?
- React Hooks 解决了哪些问题?怎么解决的?
- React Hooks 和生命周期的关系?
- React key 是干嘛用的 为什么要加?
- 对 React 和 Vue 的理解,它们的异同?
- React 设计思路,它的理念是什么?
- React 必须使用 JSX 吗?为什么使用 JSX?
- 谈一谈 react 事件机制?
- 谈谈你对 React-Fiber 的理解,它解决了什么问题?
- 哪些方法会触发 React 重新渲染?重新渲染 render 会做些什么?
- React 如何判断什么时候重新渲染组件?
- ......
您可以已经注意到了,这些问题都会强调 “为什么”,如果您现在不清楚应该怎么回答也没关系,本系列文章将会会娓娓道来,帮助大家从原理的角度去深层的思考这些问题。我希望经过本书的学习,您不仅仅可以完美的回答大部分关于 React 的问题,还能够谈笑风生,延伸到 “为什么会这样?”、“这样做有什么好处,有什么问题?” 这样的问题上,甚至能够对问题提出自己的改进措施和解决方案。
关于 React 源码相关的面试题,会有单独的章节进行讲解。