注册

从最简单的角度走上读源码

1.前言


很早前就想多看一些源码,也看过不少源码的分析,自己简单的去浏览过,但等到想静下心来自己去分析一些的时候,却一直没有时间被搁置,其实可能也是因为自己对相关操作比较陌生,潜意识里又一点抵触。最近想开始行动又在想如何开始,从哪个源码,从什么部分去入手的时候,想起若川大佬经常有一些源码的研究,并参加了他发起的源码共读活动,受益良多。本次读的部分是vue3的工具函数,这是若川哥文章的地址juejin.cn/post/699497…


这里从一个源码初学者的角度对这一次共读进行一些记录和总结


2.项目准备


万事开头难,很多时候正是因为没有想好怎样去有一个好的开始,而一直搁置。


先是在若川的引导下,我先去看了vue-next的readme和相关协作文档,其实之前也会看,但没有想法去仔细想一下,并动手去实践起来,虽然是英文的,但是可以先稍微读慢一些


vue-next贡献文档里有写到过,当有一些多个编译方式都要用的方法函数的时候,要写到share模块里,当时我会感觉这是一个很困难的部分,但还是继续去做好了


当对文档有一定的了解之后,开始把vue-next下载到本地进行浏览


git clone https://github.com/vuejs/vue-next.git

cd vue-next

npm install --global yarn

yarn

yarn build

以上流程大家应该都比较熟悉


有个要说的就是,在大家yarn的时候 很有可能也会遇到The engine "node" is incompatible with this module的错误


这是vue-next的代码不久前有一个在engine里对node版本有限制,大家只要把node更新到相应的版本就可以了,用nvm可以很方便的进行。或者用yarn install --ignore-engines 对这个限制进行无视


还有个重要的就是在我们build之后,因为vue-next的代码基本都用ts进行了重构,build完会有一个vue-next/packages/shared/dist/shared.esm-bundler.js 文件,这是对本文件夹ts的js转义输出,这里的文件位置可以在tsconfig里找到。(忽然找到一个一边学源码一边复习ts的好方法!


3.源码调试


在源码调试的时候有一个困难的事情,就是代码经过各种步骤输出后,是没有办法直接调试的,所以我们往往会通过sourceMap去进行帮助,sourcemap是一个记录位置的文件,让我们能在经过巨大变化的代码里找到我们原来开发的样子


这是贡献指南里说提供的:Build with Source Maps Use the --sourcemap or -s flag to build with source maps. Note this will make the build much slower.


所以在 vue-next/package.json 追加 "dev:sourcemap": "node scripts/dev.js --sourcemap",yarn dev:sourcemap执行,即可生成sourcemap,或者直接 build。


然后会在控制台输出类似vue-next/packages/vue/src/index.ts → packages/vue/dist/vue.global.js的信息。


我们在文件里引入这个文件,就会有效果啦~


4.工具代码


上文有说道过,当初觉得这个模块是困难的,但其实真正去看的话,很多写法其实也都是平时会用到的,我们看这类源码,要抛开其他,对一些对我们有帮助的代码写法进行学习。我们从vue-next/packages/shared/src/index.ts开始。


前边的一些其实都是为了更加方便使用和严谨,但其实并不难。但有一些我们平时没有那么常用的方法,其实某些时候也都会有用,至少都应该有印象,比如对象的方法,Object.freeze({}),还有es6的字符串方法Startwith等


还有很有用的是,在学习工具源码的过程中,复习到了一些之前的知识,比如原型链的一些相关


hasOwn:判断一个属性是否属于某个对象


const hasOwnProperty = Object.prototype.hasOwnProperty
export const hasOwn = (
val: object,
key: string | symbol
): key is keyof typeof val => hasOwnProperty.call(val, key)

toRawType:对象转字符串


const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
const toRawType = (value) => {
// extract "RawType" from strings like "[object RawType]"
return toTypeString(value).slice(8, -1);
};

这里是三个函数,我把三个放在一起去进行总结,typeof很多时候是不准的,这个时候用这个方法可以进行一些补充


比如可以分出array和普通object


// typeof 返回值目前有以下8种
'undefined'
'object'
'boolean'
'number'
'bigint'
'string'
'symobl'
‘function'

isPromise判断是不是promise


const isPromise = (val) => {
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
};

// 判断是不是Promise对象
const p1 = new Promise(function(resolve, reject){
resolve('');
});
isPromise(p1); // true

之前没有想到这种思路,很简单实用


cacheStringFunction函数缓存


const cacheStringFunction = (fn) => {
const cache = Object.create(null);
return ((str) => {
const hit = cache[str];
return hit || (cache[str] = fn(str));
});
};

5.总结


能写出这篇文章要很感谢若川哥的帮助


这一期的读源码很有收获



  1. 有了开始研究困难源码的信心和方向
  2. 对项目的github文档更加重视并懂得去理解
  3. 学会了通过sourcemap帮助我们调试源码
  4. 学习了vue工具函数的写法,复习了相关知识,并在工作中有意识借鉴

链接:https://juejin.cn/post/7010004468292911118

0 个评论

要回复文章请先登录注册