跳到主要内容

总结篇-如何有效阅读源码

前言

一流工程师天生充满了责任感和好奇心,他们大都满怀信心但却虚怀若谷,他们直接但不粗鲁,他们不推诿,他们不在乎工作边界,以团队任务而不是自己的工作任务为模板。我不止一次领教过一流工程师的威力,他们不止能把事情做对,还能把事情做好。他们能在完成开发的同时还能把团队不必要的沟通、返工和流程成本降到最低,更能防患于未然,把各种凶险消弭于无形。 --《浪潮之巅》:吴军博士讲述硅谷IT发展史

在目前读者的反馈中,说到小册里面的源码部分看起来比较头疼,很难理解。实际我在小册中放了一些源码主要为了让大家了解 React 中一些核心细节和主要流程。只有知道这些,才能更熟练的运用 React ,才能更好地解决工作中一些复杂的场景问题。接下来我把我阅读源码的心得分享给大家,希望能对大家有帮助。

如何高效阅读源码(彩蛋)

在阅读源码过程中,我遵循这几个技巧,感觉很有效果。

1 知己知彼

首先在阅读源码之前,第一步就是要明白看的是什么? 是否熟悉里面的 api? 是否在真实的项目中使用过? 如果对于同一个库,工作中使用过的开发者看源码,要比没有使用过直接看源码,容易的多。

  • 比如想看 react-redux 源码,就要先知道 react-redux 中 Provider 是做什么的 ? connect 怎么使用的,它有几个参数,每个参数有什么意义?
  • 比如想看 mobx-react 源码,就要先知道 mobx-react 中 injectobserver 的作用。

开发者对一个库或者一个框架越熟悉,看源码也就越容易,甚至如果真的精通一个框架本身,那么很有可能不看源码就猜到框架内部是如何实现的,正所谓庖丁解牛。

2 渐进式|分片式阅读

看源码千万不要想着一口气吃成个胖子,作者看 React 源码,陆陆续续看了一年,当然不是天天都在看,但是中间也没有间隔太久,如果想要快速看完源码,懂得原理,那么只能从看源码到放弃

作者看源码遵循 渐进式 ,分片式 原则。

  • 渐进式: 拿 React 为例子🌰,如果一上来就看 React 核心调和调度流程,那么一下就会蒙,就会找不到头绪,看着看着就会变成看天书,所以可以先看一下基础的,比如 fiber 类型,React 如何创建 fiber ,每个 fiber 属性有什么意义。然后再慢慢渗透核心模块,这样效果甚佳。
  • 分片式:对于一个框架的源码学习,要制定计划,化整为零,每天学习一点点,每一次学习都做好笔记,两次学习的间隔最好不要太长时间。

3 带着问题,带着思考去阅读

带着问题学习源码是最佳的学习方案,而且作者可以保证,这种方式每一次看都会有收获。即使很多开发者看源码坚持不下去,就是因为没有带着问题,没有去思考。

如果没有问题的去看源码,看着看着就会变得盲目,而且很有可能犯困。这样是坚持不下去的。

那么如何带着问题去思考呢? 作者这里举了个例子🌰,比如现在想看 React Hooks 源码。那么我写一段 React Hooks 代码片段,看一下可以从中汇总出哪些问题?

import React , { useContext , useState , useRef, useEffect, useLayoutEffect, useMemo } from 'react'
const newContext = React.createContext(null)
/* ① React Hooks 必须在函数组件内部执行?,React 如何能够监听 React Hooks 在外部执行并抛出异常。 */
const value = useContext(newContext)
console.log(value)
function Index(props){
const [ number, setNumber ] = useState(0)
// ② React Hooks 如何把状态保存起来?保存的信息存在了哪里?
let number1 , setNumber1
// ③ React Hooks 为什么不能写在条件语句中?
if(props.isShow) [ number1 , setNumber1 ] = useState(0)
const cacheState = useRef(0)
const trueValue = useMemo(()=>{
// ④ useMemo 内部引用 useRef 为什么不需要添加依赖项,而 useState 就要添加依赖项
return number1 + number + cacheState.current
},[ number ,number1 ])
// ⑤ useEffect 添加依赖项 props.a ,为什么 props.a 改变,useEffect 回调重新执行。
useEffect(()=>{
console.log(1)
},[ props.a ])
// ⑥ React 如何区别 useEffect 和 useLayoutEffect ,执行时机有什么不同?
useLayoutEffect(()=>{
console.log(2)
},[])

return <div>《React 进阶实践指南》</div>
}

从上面的一段代码中,可以提炼出的问题有:

  • ① React Hooks 为什么必须在函数组件内部执行?React 如何能够监听 React Hooks 在外部执行并抛出异常。
  • ② React Hooks 如何把状态保存起来?保存的信息存在了哪里?
  • ③ React Hooks 为什么不能写在条件语句中?
  • ④ useMemo 内部引用 useRef 为什么不需要添加依赖项,而 useState 就要添加依赖项。
  • ⑤ useEffect 添加依赖项 props.a ,为什么 props.a 改变,useEffect 回调函数 create 重新执行。
  • ⑥ React 内部如何区别 useEffect 和 useLayoutEffect ,执行时机有什么不同?

如果带着以上问题去阅读源码,相信阅读之后肯定会有收获。这种带着问题去阅读好处是:

  • 能够从源码中找到问题所在,更一针见血的了解原理
  • 能让阅读源码的过程变得不是那么枯燥无味,能够更加坚定阅读

披荆斩棘 ,勇往直前!

这本小册作者从 2020 年就开始整理,2021 年四月初开始正式写,写了正好四个月。 四个月里作者拒绝一切社交活动,没有一个周末休息过,把 React 知识点,从点到线再到面的串联起来,展现给大家,可能写的比较仓促,有一些错别字,如果给大家阅读带来不便,还请大家见谅,我会一直维护这本小册,修复错别字和不正确的地方,对小册的内容做技术翻新,对小册内容做补充,特别是持续维护的章节(第十四章,第二十六章,第二十七章)。

“路漫漫其修远兮,吾将上下而求索” ,希望阅读到这里的每一个读者,不要把掌握小册的知识点作为学习 React 的终点,而是要当成学习的起点,带着对 React 全新的认识去使用,平时工作中要多敲多练,多学习一些 React 设计模式,多写一些自定义 Hooks 。在 React 技术成长之路上披荆斩棘 ,勇往直前!

最后的最后感谢大家支持我,认可我,祝福大家早日进阶 React 技术栈,在成长的道路上我与你们同行。🙏🙏🙏

如果在阅读过程中有什么问题欢迎大家加我微信,交个朋友,微信:TH0000666,也可以关注笔者公众号 前端Sharing,持续分享前端硬核文章~

11118.jpg