摘要:源码真的这么可怕吗从以上的事例中可以看出,其实并没有。对于源码的恐惧,让我们渐渐思维固化,自己告诉自己不要去碰源码,时间长了就遗忘了还有这样一条路可走。
一个小需求
事情的起因,是昨天有一个新的需求被提出。
需求是要实现,让我们自己定制的弹出层,具备按下 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 shown window.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:欢迎关注我的公众号 “超哥前端小栈”,交流更多的想法与技术。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/100881.html
摘要:让你收获满满码个蛋从年月日推送第篇文章一年过去了已累积推文近篇文章,本文为年度精选,共计篇,按照类别整理便于读者主题阅读。本篇文章是今年的最后一篇技术文章,为了让大家在家也能好好学习,特此花了几个小时整理了这些文章。 showImg(https://segmentfault.com/img/remote/1460000013241596); 让你收获满满! 码个蛋从2017年02月20...
摘要:欢迎来我的个人站点性能优化其他优化浏览器关键渲染路径开启性能优化之旅高性能滚动及页面渲染优化理论写法对压缩率的影响唯快不破应用的个优化步骤进阶鹅厂大神用直出实现网页瞬开缓存网页性能管理详解写给后端程序员的缓存原理介绍年底补课缓存机制优化动 欢迎来我的个人站点 性能优化 其他 优化浏览器关键渲染路径 - 开启性能优化之旅 高性能滚动 scroll 及页面渲染优化 理论 | HTML写法...
阅读 1917·2023-04-25 16:19
阅读 3056·2021-11-24 09:39
阅读 783·2021-11-16 11:44
阅读 1643·2019-08-29 12:52
阅读 1114·2019-08-26 13:33
阅读 1051·2019-08-26 10:26
阅读 2182·2019-08-23 16:42
阅读 2548·2019-08-23 14:37