《编写优雅的前端业务代码》听后感

来源:互联网 发布:网络诈骗真实案例 编辑:程序博客网 时间:2024/05/22 06:28

这场知乎live主要拿了一份现实工作中的业务代码进行一步步地优化分析。每个人的收获都是不一样的。我就以我的水平去总结一下这场live,也说说我的收获。

原来的代码一共300行不到的js,用jquery写的。整个代码结构,就是前面定义少许变量,然后一堆函数,一堆事件的绑定,中间夹杂着几个函数的调用,算是初始化的功能吧。对这份代码的整体感受,代码格式整洁,有些注释,太多DOM操作,太多样式的计算看得有点眼花缭乱。

对于我这种小白水平的来说,如果要我去优化。我会做的不多,最多就是把那些函数的调用放在一块,省得找来找去的。可能会调换一下代码的顺序,更好读一些。一个函数如果业务太多,拆分成多个子函数来实现。提取一些复用的函数和变量。

然后,我们看下大神是怎么做的。

第一次优化

这一次在结构上是比较大的修改,算是一次大重构。首先用经典的立即执行函数写法把所有代码包起来( 主要作用应该是避免污染全局变量 ),一般jquery的插件都可以看到。而原始代码用的仅仅是$(function(){ //some code }),主要是为了保证在dom加载完毕之后才执行代码。

然后在代码结构上,将代码写成模块的形式。定义了一个构造函数(来模拟类), 函数内部做了一些初始化操作的事情,然后在把那些方法定义在它的原型对象(prototype)上,顺便把这个类暴露给全局变量,然后在dom加载完毕之后进行实例化。简化的框架如下:

// 立即执行函数(function($, global, doc){    var app = function(options){       // 一些变量的初始化       //  执行某些函数,进行初始化        init();     };    app.eles = {};  //存了一些元素的map,用静态变量的形式。我觉得写在上面匿名函数内部this.eles也是一样的吧!?    app.prototype = {        constructor: app,  // 修改构造器的指向       // 前面加_表示内部私有函数,一种约定习惯吧        _foo: function(){        },        init: function(){        }        // ...        // 以及 所有的函数方法     }    // 将这个模块暴露给全局变量    window.app = app;    // dom加载完毕之后,实例化一次    $( function() {        new app();    })})(jQuery, window, document, undefined)

再细节地来说,整个代码加入了生命周期的概念。生命周期的概念我听过,比如一些框架都有自己的一套生命周期,但我不怎么熟悉。对业务代码的生命周期的概念更加模糊,其实也有看过或者接触过。听完这场live之后,我理解的业务代码的生命周期,就是初始化过程中,初始化一些组件,绑定一些事件啊,然后在最后销毁这个模块的时候,将这些组件销毁,将事件解绑。我觉得主要的目的就是释放内存吧。是不是理解的对不对,或者理解地比较狭窄?

然后它还做了个小细节的优化,就是所有事件绑定的都整理到一块,写在一个eventsMap里面,用一个函数将元素和事件绑定在一块。

app.prototype = {    constructor: app,  // 修改构造器的指向   // 前面加_表示内部私有函数,一种约定习惯吧    _foo: function(){    },    init: function(){        // 初始化操作        this.initWidgets();        this.bindEvents();    },    initWidgets: function(){        // 初始化组件    },    destroyWidgets: function(){        // 销毁组件    },    bindEvents: function(){        // 绑定事件    },    unbindEvents: function(){       // 解绑事件    }    destroy: function(){        // 整个模块的销毁        this.unbindEvents();        this.destroyWidgets();     }    // ...    // 以及 所有的函数方法 }

到此,整个代码的结构都清晰了很多。

第二次优化

这次主要是细节上的优化,把常用的变量和dom元素提取出来集中管理,函数内部的一些变量也提取在函数内部的最前面,以便于复用。一个注意点就是dom的元素可以保存为一个变量,这样有利于代码压缩。因为如果你是$(‘myContent’),里面的’myContent’是无法被压缩的。还有,一个函数如果太长了,将内部部分代码抽取出来变成一个新的函数,这样可读性强一些。这些算是比较常规的优化。

第三次优化

提取了公共的基础函数库,封装在util对象中。一些if语句用三元表达式来代替,switch语句改成更加合理的方式。

第四次优化

这次优化也是一次大重构。它结合了模块化,类和继承等用ES6语法重构了一次。本来是一个300行不到的js文件,现在拆成了7个加起来500多行的js文件。

这里写图片描述

代码看得懂,可能自己写不出来,ES6还没好好地看好一遍,对类和继承理解也还没那么深刻。我觉得这里比较巧妙的是,多级继承的写法。在定义的时候,将父类作为函数变量,使得最后myApp的类继承自一个高阶函数的样子。我是第一次见过这样的写法。抽出来这些代码的关键部分:

// myApp.jsimport  ...  from .......class myApp extends drag(resize(base(config))){    constructor( options ){    }    ...}export default myApp// resize.jsimport ... from ...let resize = ( superclass ) => class extends superclass {    constructor(){    }    ...}export default resize

总之,这次改造非常高大上,需要很好地掌握模块化,类,继承,以及ES6的语法糖。

这次live,从一个很一般的js业务代码一步一步地重构,的确挺有收获的。

最后大神对这次live进行了总结。我用我的话来说一下那些我理解的点:

  • 合理的选择器:无意义的样式,以 “j-“为前缀
  • 选择器的统一管理
  • 事件绑定的统一管理
  • 生命周期的概念
  • 方法的复用
  • 模块化

转载请注明出处:http://blog.csdn.net/fen747042796 野草园
欢迎关注我的知乎:野蛮的小小芬

0 0
原创粉丝点击