zoukankan      html  css  js  c++  java
  • 【杂谈】是谁发明了轮子?有关前端组件的些许思考与总结

      从业时间稍微长一点我们都会碰到一个问题:

        “我们每天都在进行重复的劳动,有什么简便的方式让我们摆脱这一枯燥乏味的无差别时间消耗么?”

      也即由于最近又一次造了一次“轮子”的经历,让笔者产生了写下此文的想法。说正事之前让我们简单回顾下,这个“轮子”的来历。

      其实这大抵也是人类史上的一个谜团,相传有人说是我们的老祖宗公输班在一次偶然的机会下发明的,但是据说他看到了“风吹着草团滚动的情形”,天纵英才的他就灵感涌现的发明了轮子,当然,也有人说轮子的前身实际是“圆木”,就好比古埃及建造金字塔的时候,运输硕大的巨石,不依靠圆木一类的工具,几斤是不可能的;还有考古学家在波兰的底下墓地中发现了公元4700年前刻在石壁之上有关车轮的描述。

      总的来说,也许每个文明都造出了轮子,虽然到底是哪个文明先发明了轮子是莫衷一是的,但是他们发明轮子都出于一个共同的目标,提供工作效率,降低工作负担,这似乎是值得肯定的事实。

      回到之前的话题,笔者最初“造轮子”也就是写组件的初衷也基于此,而重新“造轮子”的原因确实因为团队的技术结构的改变。之前的组件并非基于新的技术架构而构建,所以为了适应新的技术架构,必须重新实现一次组件。到这里这个“造轮子”的味道就变得很奇怪了,本来为了避免重复劳动而产生的避免重复劳动的行为,最终还是引起的了重复劳动,想着是不是有些本末倒置了呢?

      写到这里也让笔者想起了去年前端圈子里的比较轰动的事件,本文简称“真阿当”事件。随着时代的进步,技术的发展,前端这个之前并不太受重视的圈子得到了越来越多的关注,于是也有越来越多的工具、体系建设的出现,新的“轮子”不断涌现,但是谁又真的能确信,那些东西真的是这个领域发展真的需要的?谁又能确信,过去的旧轮子真的会被淘汰?

      其实这个话题本身就是一个罗生门,对于现实发生的事件,每个人都有基于自身经历所独特的认知和理解,这便是人性。理解了这点,我们且放下关于对错的争论,回过头去看看这些轮子的出现给我们的工作生活带来了哪些变化?

      在jQuery统治前端圈子的时候,几乎不论大大小小的公司都会使用jQuery,而其本身高效易用的特性,也是其当之无愧的成为了那个时代最快的最好的轮子。随着HTML5时代的到来,昔日业界霸主终将走下神坛,现在的世界,React、vue等等一些列新的“轮子”相继登场,它们在带给我们的,不仅仅是优化开发模式这么简单的体验了,高度的封装,缜密的逻辑思想,都是值得我们学习的地方,但忽然有一天,我们突然需要dom操作了,我们却懵在了原地,不知所措。

      jQuery最令人称道的地方,除了极其强大的链式调用(当然兼容性也是很大的有点),然后就是简易的dom操作,而到了新的时代,新的轮子们通过对dom的抽象,通过使用模板引擎或者其他的方式,或多或少的封装了dom,准确的说应该就是隔离了dom,但是这个原本对于我们来说是一个很好的消息(virtualDom的出现无疑提高了dom渲染的性能),而对于那些并不了解dom的新人来说,却是一个无疑的灾难。

      另外,相信很多童鞋也有做SEO的经历,如果面对搜索引擎优化,看似与技术并无太多关系的话题(的确,很多时候我们只是从“词的语义”的层面去优化搜索引擎),但是到了新时代,到了隔离了dom操作的时代,这却不得不引起我们又一次的重视(相信我,当你看到一整个页面确实用div标签拼接的时候,你也会有同样的感叹),要知道HTML5不仅提供了新的特性与能力,在语义化上它也做出了更明确的进步,试图通过规范去降低SEO的难度。

      其实聪明的你也许已经发现,笔者的观点,也即

        “没有最好的轮子,只有最适合某个场景、最适合某种业务、最适合某个具体团队在某个历史阶段局部最优解的选择罢了。”  

      看着这个模糊的不行的结论笔者自己也笑了XD

      洋洋洒洒地吹了那么久的牛,也该做点实事了,以下便分享和记录一下笔者目前的对前端组件认知吧:

      1、API到底该如何设计

      这也是个老大难的问题,如上文所说,“一千个读者,一千个哈姆雷特”。什么样的API是最合理的?这是笔者在开发组件遇到的最头疼的问题。简单的API不能提供足够的功能,复杂的API又提高了组件使用的门槛,而在这一切之前还有一个莫大的前提,你得能用尽可能精简的词汇准确的表达你需要表达的意思,我们可以参考下经典而又复杂的dom操作的几个API去找找灵感:

        getElementById

        getElelemtsByClassName

        getElementsByName

        getElementsByTagName

    还有HTML5时代的两个等价API:

        querySelectorAll

        querySelector

      笔者最后使用了设计界的一个基本原则——“KISS”,Keep it simple & stupid,极力保证api使用的低门槛(至于原因后面会提到)。

      2、到底该如何阻止事件穿透

      相信大家在移动端开发都碰到过事件穿透的问题,有点击事件穿透,有滚动事件穿透(准确的说这个其实并不能叫穿透),公认的阻止穿透的方法是event.preventDefault(),但是对于滚动的穿透则没有那么简单(这种情况通常发生在弹出层上),通常我们都需要设置底部(也就是html)的overflow:hidden(一些情况别忘了margin),但是这样会导致页面的scrollTop重置,在弹出层消失的时候我们还需要去hack它,所以,我们还会采取另外一种曲线救国的方式去实现:即通过prevent touchmove事件阻止弹出层的滚动事件的发生以阻止其冒泡,同时为了解决弹出层不能滚动的问题,我们可以通过touchmove,利用transform去自己实现scroll(当然你也可以使用iscroll,也许这也正是iscroll流行的原因)。

      3、有关全组件和半组件之争

      简单地说,对于固定或者相对固定的持续稳定的业务,全组件能够实现一个究极目标,即“最后的开发并不需要写一句逻辑代码,而只是需要不断地调用组件就好了”。但是这是一个究极且十分理想的情况,业务发展的速度,技术发展的速度,行业发展的速度,世界变化的速度,一切的一切都让我们朝向也最终将走向提供最核心最公共的功能的半组件化的道路上。

      4、组件的兼容  

      可能是笔者组件开发的特殊性,笔者考虑的组件的特殊的兼容场景,也即笔者期望笔者的组件在react和类react体系中达到某种“巧妙”的平衡,就笔者的团队而言,不久的将来很有可能同时跑着以react、preact、inferno为基础实现的webapp(至于为什么,聪明的你可以思考下XD),对于三种相似的平台,笔者还是抱着一颗想要全平台兼容的美好愿景的,当然现实是蛮残酷的(preact和inferno都满满的吐槽了react关于refs糟糕的实现,preact则直接表示不予支持,inferno去掉了一些react自作聪明的语法糖,但是还是阉割了一些功能)。当然为了达到这个目的,大量的测试总是避免不了的。

      另外值得一提的就是移动时代的双平台兼容,受够了pc上IE带来的各种丧心病狂的feature之后,在移动端是不是好点了呢?还是以滚动举例,ios上webview滚动的时候js是阻塞不执行的,一直到滚动结束才会执行一次,那么我们经常需要使用的吸顶menu不就没法实现了么?关于这点ios为自己的坑买了单,提供了position:sticky来做兼容,解决了这个问题。

      再举一个例子,overflow属性相信大家都用得很多,虽然通常都是在设置hidden这个属性上,不过在某些情况下,存在着需要使用其他value的情况,比如这句“overflow:auto”,在android上没有问题,需要滚动的时候就出现滚动条,不需要滚动的时候这默认不显示滚动条,但是这样设置在android上没什么问题,在ios上则会出现滚动效果很奇怪的情况(native快速回弹的效果居然没有!)这个时候还需要对ios添加“-webkit-overflow-scrolling: touch;”属性,才能达到预期的效果,当然,如果你一开始就设置为“overflow:scroll”的话,就能够开启这个效果,不过虽然手机上没问题了,默认scroll在PC上会出现一个滚动条也是一个很尴尬的事情,也正因为如此,才会有这个属性来解决这个奇异问题吧。

      当然,这些还是比较理想的情况,更复杂的是在Android的上,不同的系统内核的兼容性才是真正头疼的地方,更有甚者,还有某厂的自研内核,打着完美支持webgl的口号,连Array.prototype.find都不支持,实在令人啼笑皆非。所以虽然历史前进到了mobile上,但是兼容依然是一个任重而道远的工作。

      5、组件的使用

      组件的使用?为什么的组件的使用会有需要总结的地方呢?让我们再看两个例子:

      埃德温·德雷克,他是美国第一口油井的钻井者,也可以说他就是石油的发现者,但是,他并没有享受到发现石油带来的任何红利,而是潦倒的过完了自己的一生。

      托马斯·爱迪生,这个大家应该都知道,但是他其实并不是发明电灯的人,他甚至还是一个号称“飞机是人类历史上最愚蠢的发明的人”,但是,他最终因为他的“发明”载入史册,名留青史,他生前的那一堆胡话都变成了轶事。

      人们常常以为是爱迪生发明了电灯,其实,从来都不是他发明的,但是,他之所以伟大,是因为他真正的实现了电灯的商业化。而德雷克上校,却没有。(限于篇幅笔者便不继续展开了)回到我们的话题,你的组件、你的轮子发明的作用就是为了被使用,而如何让别人能够更好的使用,这才是你的组件最大的目标。而针对笔者所在团队的人文环境和历史阶段,笔者也基于自己的判断做出了自己的选择。

      “对人类来说,你发明了什么也许并不重要,真正重要的是你发明了什么对人类能够切实起到作用的东西。”

      6、组件的未来

      虽然笔者选择的半组件的方式,但是这并不意味着组件之间的关系就只是单纯的依赖。随着整个组件体系的完善,从基础组件到最终成型的组件,高阶组件的出现似乎也是一种必然的选择(虽然笔者仍在使用mixin),也是为了之后的可扩展性,基类组件的抽象则是组件工作开始是最重要的一环。

      暂时能总结的就这么多了。在过去的2016年,笔者的职业生涯迎来了一轮新的机遇与挑战,也即由这些挑战,让笔者能够站在比过去更高的维度上去思考,前端的发展的潮流给作为一个工程师的我所带来的一切。

    同时,在时代之光点亮了笔者的技术之路的时候,也浅浅的在笔者的生活之路上,勾勒出了一抹新的色彩。

      

  • 相关阅读:
    Js使用WScript.Shell对象执行.bat文件和cmd命令
    wscript运行js文件
    Linux基础tree命令
    使用libssh2库实现支持密码参数的ssh2客户端
    zlib库剖析(1):实现概览
    Linux设置编译器环境变量
    开源的zip_unzip库
    黑客入门之单机游戏外挂
    linux定时任务的设置 crontab 配置指南
    Linux crontab定时执行任务 命令格式与详细例子
  • 原文地址:https://www.cnblogs.com/mfoonirlee/p/6501549.html
Copyright © 2011-2022 走看看