博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
「读懂源码系列1」还在恐惧读源码?看完这篇就不怕了
阅读量:7097 次
发布时间:2019-06-28

本文共 3416 字,大约阅读时间需要 11 分钟。

一个小需求

事情的起因,是昨天有一个新的需求被提出。

需求是要实现,让我们自己定制的弹出层,具备按下 ESC 也能退出的功能。我把任务交给了同组的小伙伴S去实现。(这个项目用到了vue技术栈,以及饿了么的UI框架。)

我开完会回来,发现他还在处理那个功能,但好像遇到了什么瓶颈。于是,我就问他,卡在了什么地方。

小伙伴S说,他百度了不少资料,还查了官方文档,并且尝试其中的办法,但就是无法触发按下 ESC 的回调方法,很是郁闷。我看了他的代码,他的写法是这样的:

...
...handlePressEscape () {    console.log('press escape!');},...

他的想法不错,因为是自定义的弹出层,所以就想着把 keydown 事件,绑定在最外层的 div 上,让整个弹出层都能监听到。

他给我看了他查的资料,几乎都是在 input 上绑定 keydown 事件的例子,而 vue 的官方文档里也是类似的例子,实践后却陷入了瓶颈。但是他忽略了一个问题,keydown 事件,并非绑在任意一个标签上,都会起作用

一种思路

我没有直接把答案告诉他,而是给他提供了一个思路:在我们常用的 element-ui 的 el-dialog 组件里,有个属性叫做 close-on-press-escape,它的解释如下图:

图片描述

从文档的解释,可以看出 el-dialog 在默认情况下,已经实现了我们需要解决的需求。所以,我让他看看 el-dialog 的源码,是如何实现的。

他一听要看源码,就露出了恐惧之情。

图片描述

源码是所有框架和API的根基,因为比较复杂深邃,所以让人很抗拒。我自己也经历过这个阶段,所以非常理解他的心情,鼓励他一起做一次尝试。

查找源码

首先,我们在 node_modules 里,找到了 element-ui的文件夹,它大致长这个样子:

图片描述

接着,我们找到了 packages 里的 dialog 文件夹,再从 index 入口,找到了组件 component.vue。可是,点进去找了半天,也只找到个 closeOnPressEscape 属性的定义,却没有实现的方法。

...closeOnPressEscape: {    type: Boolean,    default: true},...

这么神奇么?只定义一个属性,就能实现一个事件的交互了?

感觉不太可能啊?!? 为了揭开迷雾,继续找。。。

仔细浏览了 component.vue 文件,发现在 script 里,引入下面 3 个文件:

import Popup from 'element-ui/src/utils/popup';import Migrating from 'element-ui/src/mixins/migrating';import emitter from 'element-ui/src/mixins/emitter';...

在第一个引入的 Popup 中,竟然也发现了 closeOnPressEscape,感觉似乎找对方向了。

但令人沮丧的是,Popup 中同样只有 closeOnPressEscape 的属性定义,却没有实现。不过,它却引入了另一个辅助文件 PopupManager,再点进去找。

哇!终于找到了!它的实现,是这样的:

// handle `esc` key when the popup is shownwindow.addEventListener('keydown', function(event) {    if (event.keyCode === 27) {        const topPopup = getTopPopup();        if (topPopup && topPopup.closeOnPressEscape) {            topPopup.handleClose                ? topPopup.handleClose()                : (topPopup.handleAction                    ? topPopup.handleAction('cancel')                    : topPopup.close());        }    }});

原来,是在 window 上添加了事件监听 keydown,当监测到是 ESC 的 keyCode 时,则执行相关操作。

模仿源码

ok,现在已经知晓了原理,那就按照我们的实际需求,模仿改造一下:

...props: {    ...    closeOnPressEscape: {        type: Boolean,        default: true    }},...mounted () {    window.addEventListener('keydown', this.handlePressEscape);},destroyed () {    window.removeEventListener('keydown', this.handlePressEscape);},methods: {    ...    handlePressEscape (event) {        if (this.closeOnPressEscape && event.keyCode === 27) {            this.handleClose();        }    }}

在上述实现中,有2个需要注意的点:

  • 代码方面,在 mounted 中,给 window 添加事件监听之后,要记得在 destroyed 时,去除监听。
  • 业务方面,这是一个我们定制的通用的弹出层组件,所以在 props 中定义了一个 closeOnPressEscape 属性,以方便在某些业务场景下,不需要按 ESC 就退出这个功能的时候,直接设置它为 false 即可。

到此为止,整个事件画上了圆满的句号。

源码真有那么可怕吗?

源码一词,乍一听就是神秘、高大上、吊炸天的代名词,让很多的前端同学闻风丧胆。回想当初,我也曾一度对它有一股深深的恐惧。

源码真的这么可怕吗?

从以上的事例中可以看出,其实并没有。例子中的element-ui源码并不复杂,我和小伙伴S一起看源码时,他也大概都能看得明白。最后因为弄懂了背后的原理,进行简单应用,比较轻松地就解决了问题。

对于源码的恐惧,让我们渐渐思维固化,自己告诉自己不要去碰源码,时间长了就遗忘了还有这样一条路可走。

面试中的应用

关于对源代码的考察,我也会经常应用在面试中。在面试中,如果候选人给我的感觉不错,我的惯用伎俩是问下面这个问题:

刚才你说到,用过一段时间 xxx 框架,xx API属性也用过,也很清楚它达到的效果。

那么现在,如果需要你实现一个类似的效果,抛开 xxx 框架以及 xx API属性,

你会如何去实现,有没有其他思路?

这个问题,意在考量候选人的思维方式和解决问题的能力,以及把他思考的过程阐述清楚的表达能力。这三种能力,往往比使用过某些框架的经验,更让我看中。

这道题的回答思路,其实就是可以通过挖掘源码,去实现功能。另外也可以通过海量地查找资料,发现原生js的实现方式,但这条路没有直接挖掘源码来得快。在遇到实际的业务问题的时候,参考源码的原理和写法,往往能更快地解决问题。

这是我自己对这道题目,给出的答案。

一点点思考

昨天的案例,引发了我的一连串思考:

现代框架的确降低了前端入门的门槛,提高了开发效率。

但是,在使用这些框架的过程中,我们到底学到了什么?

脱离了框架和它的API,我们脑海中还剩下些什么?

以至于,当下一个更新更棒的框架出现的时候,我们是否能够用已经学到的知识,帮助自己更迅速地上手?

知其然,并知其所以然,学习所有的知识都应当有这种探索精神。我们不仅仅是代码的搬运工。领悟这些深层次的原理,比起仅仅熟练地掌握一门框架,要实用得多。

PS:欢迎关注我的公众号 “超哥前端小栈”,交流更多的想法与技术。

1877824921-5c2b6771cf4b9_articlex

转载地址:http://wfeql.baihongyu.com/

你可能感兴趣的文章
善用思维导图来整理发散的思维
查看>>
2014百度之星 Party
查看>>
win10 adb(Android Debug Bridge)导出日志
查看>>
js选择栏select插件 简易
查看>>
sql中truncate 、delete与drop区别
查看>>
【转】养成一个SQL好习惯带来一笔大财富
查看>>
BZOJ1087[SCOI2005]互不侵犯——状压DP
查看>>
SQL2005 2008配置错误,无法识别的配置节 system.serviceModel machine.config配置文件有问题...
查看>>
Scala 学习笔记之集合(8) Try和Future
查看>>
Debian9 安装后的配置笔记
查看>>
JSON文件存入MySQL数据库
查看>>
Lecture 2
查看>>
CSS overscroll-behavior
查看>>
【枚举+数学】【HDU1271】整数对 难度:五颗星
查看>>
[20171113]修改表结构删除列相关问题3.txt
查看>>
面向对象聊天机器人
查看>>
课后笔记--html
查看>>
使用dll查看器dll文件中的内容
查看>>
iOS中系统自带正则表达式的应用
查看>>
Quartz 2D编程指南(7) - 阴影(Shadows)
查看>>