最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 「小议」 我从读源码中收获到了什么?阅读源码那点小事

    正文概述 掘金(我不是外星人)   2021-03-10   430

    一 前言

    说到源码,大家脑海里可能浮现出四个字 我太难了???。读源码貌似和我们遥不可及,因为在日常工作中,我们基本掌握在熟练的程度上,就能够满足工作需求,即便是想看源码,也会被源码复杂的逻辑拒之门外,成为了我们心中挥之不去的阴影。那么我们真的有必要阅读源码吗? 我以一个过来人的角度看,答案是肯定的,阅读源码不只是停留在源码层面,它还会带来一些附加的价值 。

    笔者读过很多源码,比如 主流前端框架 vue2.0,vue3.0 ,reactnode框架 express , koa,和它们衍生生态 react-router,react-redux , dva 等等。 要说在阅读源码的过程,痛苦么?我感觉过程是痛苦的,但是读完之后,就会感觉收获颇丰,感觉付出都是值得的。接下来我们一起探讨一下,阅读源码那些事。

    二 为什么读源码?

    1 为了面试

    一场面试题的思考?

    假设这是一场面试。

    面试官:说一下vue2.0响应式原理 ?

    第一位应聘者:object.defineproperty()拦截器属性,拦截set, get

    打分:4-5分 这样的答案似乎很难说服我,只能证明面试者对这个知识点有备而来。

    第二位应聘者:在第一位基础上,说出了收集依赖的dep对象,负责渲染更新的渲染watcher,递归响应式等等,并能够介绍它们的原理和作用。

    打分:6-7分 这样的答案,已经很符合标准了,至少说了vue响应式的核心,说明应聘者至少深入了解过。

    第三位应聘者:一方面从初始化 data 开始,到解析 template 模版,进行依赖收集。另一方面能够从 data 改变,通知渲染 watcher 更新,到页面变化,把整个流程说明白。

    打分:8-10分 这样的答案,是非常完美的,能够从源码角度入手,说明应聘者很深入原理,读过源码。

    从一道面试题,就能看出一个应聘者的对于框架的认知程度。而阅读源码就是从底层开始全方面认识框架的最佳方式。而且如果把源码搞得明明白白。可以让面试官刮目相看。甚至能够‘吊打’面试官??。

    2 更清晰的运用框架

    阅读源码的过程中,能够了解底层是怎么运作的。如果在工作中遇到某些问题,如果读过源码,就会找到办法,问题也就会迎刃而解。

    一个bug案例引发的思考 之前见有同事遇到过这么一个问题。

    <el-select v-model="value" >
      <el-option  
        v-for="(item,index) in list" 
        :key="index" 
        :value="item.value"
        :label="item.label"
       />
    </el-select>
    

    可能业务场景要比这个复杂,大致是如上这么样的。出现一个问题就是,每次改变 list ,然后重新选择 option 的时候,会发现绑定的 value 数据改变了,但是视图没有发生变化

    如果没有对 vuediff 算法有一定了解,肯定会对这个现象一脸蒙蔽,明明数据已经改变了,但是视图为什么没有变呢?what?

    「小议」 我从读源码中收获到了什么?阅读源码那点小事

    如果看过 diff 算法,和子节点 patch 过程的同学,就会发现,这个问题主要来源于,用 index 作为 key ,在一次更新中,虽然数据改变了,但是根据 index,复用了错误的元素节点,导致了视图和数据不对应的情况。

    对于框架或者开源库,如果我们在使用中遇到了问题,与其在 GitHubissue 等待解决,不如亲自去看看源码,也许答案就在其中。正所谓蓦然回首,那人却在灯火阑珊处。

    3 提高编程能力,拓展知识盲区

    我个人觉得,阅读源码绝对是提高变成能力,拓展知识点的捷径。为什么这么说。我们先看两短经典的代码片段:

    no 1 redux compose

    export default function compose(...funcs) {
      if (funcs.length === 0) {
        return arg => arg
      }
      if (funcs.length === 1) {
        return funcs[0]
      }
      return funcs.reduce((a, b) => (...args) => a(b(...args)))
    }
    

    这是前端领域经典的中间件案例,代码精简,却堪称神来之笔。我们可以学习源码中的,编程手法,即使写不出如上这么经典函数,也能明白什么时候使用继承,什么时候用闭包

    在阅读源码过程中,会有很多高级用法和我们很少用到 api , 我们可以有效对知识点进行扫盲。

    no2 vue3.0

    vue3.0 /reactivity/src/reactive.ts

    const rawToReactive = new WeakMap<any, any>()
    const reactiveToRaw = new WeakMap<any, any>()
    const rawToReadonly = new WeakMap<any, any>() 
    const readonlyToRaw = new WeakMap<any, any>() 
    

    vue3.0 中做保存依赖收集关系的几个 WeakMap ,引发了我对 WeakMap 以及垃圾回收机制的思考? WeakMaps 保持了对键名所引用的对象的弱引用,即垃圾回收机制不将该引用考虑在内。只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要, WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。

    阅读源码,一方面有助于我们写出诗一样的代码,另一方面,扩充了我们的知识面。总之,真香

    「小议」 我从读源码中收获到了什么?阅读源码那点小事

    4 培养设计思维和架构能力

    优秀的源码有着纵览大局,运筹帷幄的思维,和中流砥柱的架构能力,这对一个正在进阶或者正打算进阶的工程师来说,是最缺少的。

    也许你疯狂的补习这知识点,疯狂看这博客,疯狂刷着编程题,但是接手一个大的工程项目的时候,还是会手足无措,最后搞得一塌糊涂。这是为什么呢,也许就真的是缺少那么一丢丢设计思维和架构能力。

    人生的三种境界和阅读源码的三种境界是一样的。慢慢的自己编程能力会受到潜移默化的影响。

    当你刚开始看源码的时候,看自己的代码还是自己的代码。但是慢慢的,你会发现自己写的代码,受到了源码的影响,已经不像是自己最初的样子,当你日复一日的坚持,你就会明白源码真正架构设计,并能够自己设计架构,代码中有了自己的灵魂,你会发现自己的代码还是自己的代码,原因是自己进步了,能够有能力去把控全局。

    「小议」 我从读源码中收获到了什么?阅读源码那点小事

    三 怎么样读源码

    上面讲述了阅读源码的好处,接下来我们讲一讲怎么有效阅读源码。

    1 化整为零

    冰冻三尺,非一日之寒,阅读源码也不是一朝一夕的事情,我们要有计划的去阅读源码。一天抽出时间看一点,然后重点记笔记,可以是 md,可以是手写的笔记,总之要把核心内容记录下来,因为一是好记性不如烂笔头,可以加深我们的印象。二是在每次阅读之前,都把上一次的笔记拿出来看看,做到完美的衔接。把整个源码分割成多个模块,一点点去消化,不要想着一口气把源码看完,这个是不现实的。

    这是笔者在做vue3.0源码阅读解析过程中记录的笔记。

    「小议」 我从读源码中收获到了什么?阅读源码那点小事

    react 源码阅读解析过程中,记录的笔记:

    「小议」 我从读源码中收获到了什么?阅读源码那点小事

    2 三思而后行

    这个是笔者阅读源码的精髓所在。三思而后行,在阅读源码的时候先问几个为什么?带着问题去看源码会起到事半功倍的效果,为什么这么说呢?如果不带着问题阅读,就会处于一种无目标,盲目的状态,在这种状态下,尤其看无聊和繁琐的源码,就会精力不集中,长时间就会犯困,无法坚持下去。

    在阅读源码之前,首先想几个问题,带着这几个问题去源码中找答案,

    例子?一:

    vue3.0响应式原理之前,先提几个问题:

    • 1 vue3.0怎么构建的响应式,reactive API到底做了什么?
    • 2 effectreactive 是什么关系?effect 如何取代 watcher ?
    • 3 如何收集的依赖?
    • 4 通过 this.a 改变,是怎么做到视图对应更新的。

    例子?二

    在阅读 react-redux 的时候,我会先提这么几个问题:

    • 1 为什么要在 root 根组件上使用 react-reduxProvider 组件包裹?
    • 2 react-redux 是怎么和 redux 契合,做到 state 改变更新视图的呢?
    • 3 provide 用什么方式存放当前的 reduxstore, 又是怎么传递给每一个需要订阅 state 的组件的?
    • 4 connect 是怎么样连接我们的业务组件,然后更新已经订阅组件的呢?
    • 5 connect 是怎么通过第一个参数mapStateToProps,来订阅与之对应的 state 的呢?
    • 6 connect 怎么样将 props,和 redux的 state 合并的?

    带着这些问题去阅读源码,就会在源码中仔细去寻找这些问题的答案,如果找到了答案,并解释了原理,也会有不错的成就感。

    3 提炼精髓

    这一步对于阅读源码也是非常重要的,我们要学会提炼源码的精髓,以 react 为例子,react 个别函数,可能几百行,甚至上千行,但是除去服务端渲染,开发环境的警告 __dev__ ,context 上下文的处理,和一些判断等等,真正的核心逻辑代码,也许就那么几行和十几行,所以我们不需要去扣源码中的每一行代码,只需要搞清楚核心逻辑就好。

    我们拿react源码为例子:

    react/react-reconciler/ReactFiberClassComponent.js

    这个文件下,有一个 constructClassInstance 方法,用于 new 我们的组件实例。这个方法大约有 200 行左右,但是我给它进行提炼之后,代码如下

    function constructClassInstance(
      workInProgress, // 
      ctor,    // 我们的 component 
      props,  //  组件的 props 
    ){
      /* 这里实例化 我们的component */
      const instance = new ctor(props, context);
      /* 给当前 组件实例 ,挂上 updater 对象,用于组件渲染更新 */   
      adoptClassInstance(workInProgress, instance);
    }
    

    核心的代码只有这区区几行,所以在阅读源码的流程中,提炼精髓也是十分重要的。

    4 真枪实弹

    实践是检验真理的唯一标准。如果想搞清楚源码,不要单独停留在的层面,也要真正去一遍源码。 这样一来我们可以在 github ,克隆下来源码。然后在关键的上下文,可以 debugger 或者 console

    步骤如下:

    github 下载文件。

    然后进行debugger或者 console。

    接下来把源码单独抽出来,打包。

    放入我们的demo项目进行验证。

    此时我们要改变一下路径。因为原来我们的 package 是放在 node_modules 中的,现在路径改了,所以注意路径问题。

    5 因材施教

    并不是所有的框架源码都需要一个固定的模式去解析的。这一点笔者就吃了苦头。我们先来说一下背景。

    笔者在阅读 vue2.0,采用集中式阅读,就是从new Vue为入口,然后逐步向代码深层去挖掘。最后将各个模块串联起来。

    在阅读完vue2.0的核心原理后, 想要以同样的模式去阅读 react,发现此方案根本行不通,因为react 有很多模块,比如 react, react-reconciler ,react-dom,scheduler,有好几千个函数方法,看着看着就蒙蔽了,即使 debugger ,效果也是甚微,无法把各模块功能串联起来,形成体系。

    后来,开始阅读一些大佬的文章,先明白每一块干了些什么,有什么作用,然后一块块的串起来。最后再去阅读源码,发现效果甚佳。

    案例: vuereact

    vue 集中式阅读源码

    vue 源码适合集中式阅读,就是从 new vue() 开始,到初始化 data ,建立响应式 ,patch 元素节点,解析 template 模版,注入依赖,挂载真实 dom ,一气呵成,一条线串起来。

    react 发散式阅读源码

    react 需要一种发散式的阅读方法,就是你需要先明白,reconciler,scheduler,expiration time,请求关键帧等等,具体是干什么的,有什么作用,然后像搭积木一样,把它们搭起来。

    6 水滴石穿

    把值得做的事坚持下去,再把坚持做的事努力做好。 既然选择阅读源码,就要坚持下去,笔者刚开始看源码的时候也是很痛苦,曾经几度想放弃,但是后来按照上面方法,坚持下去,终于养成了好习惯,现在完全能够注意力集中的阅读源码,而且过程感觉也不像当初那么无趣。

    听说过21天效应,如果一天一天坚持下去,用不了多久就能养成一种阅读源码的好习惯,相信那个时候,我们比如尝试用一个新的 package 的时候,忍不住先去 github 上拉下源码瞧瞧。

    四 收获与总结

    关于收获

    看源码的习惯坚持了差不多二年了,收获感觉还是蛮多的,首先无论是从知识储备还是编程写法或者设计架构上,都有很大的进步,也尝试了写了自己的开源项目,并下定决心好好维护下去。

    rux 一款redux和react-redux状态管理工具

    react-keepalive-router缓存页面路由

    总结

    以上就是我在阅读源码过程中的所感所悟,路漫漫其修远兮吾将上下而求索,在阅读源码的路上,能坚持下来,将会有一片美丽的风景。

    手留余香,阅读的朋友可以给笔者点赞,关注一波 ,陆续更新前端超硬核文章。接下来将写一篇react-redux源码文章。

    源码文章汇总

    vue3.0源码系列

    • vue3.0 响应式原理(超详细) 200+ 赞?

    • 全面解析 vue3.0 diff算法 100+ 赞?

    • vue3.0 watch 和 computed源码解析 30+ 赞?

    react源码系列

    • 源码解析-这一次彻底弄懂react-router路由原理 70+ 赞?

    • 源码解析:一文吃透react-redux源码


    起源地下载网 » 「小议」 我从读源码中收获到了什么?阅读源码那点小事

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元