代码重构(编写优雅的前端代码)

代码重构(编写优雅的前端代码)

1.自执行函数,严格模式

将当前的模块对象写在一个自执行函数内。

需要使用ES5的严格模式。

该模块需要用到的全局变量需要用入参的方式传入自执行函数,供函数内部使用。

(function (global, $, doc, lsObj, zhugeSwitch, zhuge) {
    'use strict';
    /* 这里是代码 */
})(this, this.jQuery, document, lsObj, zhugeSwitch, zhuge);

2.构造函数与原型

为当前模块对象创建一个构造函数,和他的原型。

我们将构造函数作为模块的入口函数。入口函数里通常会执行初始化变量、绑定事件等等。

(function (global, $, doc, lsObj, zhugeSwitch, zhuge) {
    'use strict';
    var something = function(){

    };
    something.prototype = {
          constructor: something,
    }

})(this, this.jQuery, document, lsObj, zhugeSwitch, zhuge);

3.选择器统一管理

将选择器对象写在类属性中。

将初始化选择器的函数写在原型中,在构造函数内调用。

    var something = function(){
        this.initializeElements();  
    };
    something.Eles = {
        name: '.name',
        password: '.password',      
    };
    something.prototype = {
        initializeElements: function () {
            var eles = loginClass.Eles;
            for (var name in eles) {
                if (eles.hasOwnProperty(name)) {
                    this[name] = $(eles[name]);
                }
            }
        }   
    }

4.事件统一管理

  1. ##### 将事件Map统一写在构造内。
    var something = function(){
        this.eventsMap = {
            'focus .name input': 'nameFocus',
            'blur .name input': 'nameBlur',
            'focus .password input': 'pswdFocus',
            'blur .password input': 'pswdBlur',
            'click .btn': 'login',
        };        
    };
  1. ##### 将事件要触发的函数写进原型中。

(注意此时this的指向)

  something.prototype = {
        login: function () {
            var p = this.passwordInput;
            var n = this.nameInput;
            var pt = this.pTip;
            var nt = this.nTip;
            this.nameVal = n.val().trim();
            this.passwordVal = MD5(p.val().trim());
            var nameVal = this.nameVal;
            var passwordVal = this.nameVal;
            var phoneReg = /^1\d{10}$/;
            if (nameVal == "" || nameVal == null) {
                nt.text('手机号码不能为空');
                p.val('')
            } else if (!phoneReg.test(nameVal)) {
                nt.text('您输入的手机号码不正确');
            } else if (passwordVal == '' || passwordVal == null) {
                nt.text('');
                pt.text('密码不能为空');
            } else {
                nt.text('');
                pt.text('');
                this._requestIfTelregisted();
            }
        },  
  }
  1. ##### 我们会使用事件代理的方式对这些事件进行循环绑定。

在原型中书写一个扫描事件Map的函数。

  something.prototype = {
        _scanEventsMap: function (maps, isOn) {
            var delegateEventSplitter = /^(\S+)\s*(.*)$/;
            var type = isOn ? 'on' : 'off';
            for (var keys in maps) {
                if (maps.hasOwnProperty(keys)) {
                    if (typeof maps[keys] === 'string') {
                        maps[keys] = this[maps[keys]].bind(this); //改变this的指向
                    }
                    var matchs = keys.match(delegateEventSplitter);
                    $('body')[type](matchs[1], matchs[2], maps[keys]);
                }
            }
        },        
  }
  1. ##### 在原型中写入以下函数,优化我们的逻辑。
  something.prototype = {
        initialization: function () { //初始化
            this.bindEvent();
        },
        bindEvent: function () { //绑定事件
            this.initializeOrdinaryEvent(this.eventsMap);
        },
        unbindEvent: function () { //解绑事件
            this.uninitializeOrdinaryEvent(this.eventsMap);
        },
        initializeOrdinaryEvent: function (maps) { //绑定普通事件
            this._scanEventsMap(maps, true);
        },
        uninitializeOrdinaryEvent: function (maps) { //解绑普通事件
            this._scanEventsMap(maps);
        },    
        _scanEventsMap: function (maps, isOn) { //扫描事件地图,绑定或者解绑
        },        
  }
  1. ##### 在构造函数内调用初始化函数。
    var something = function(){
        this.initialization();        
    };

5.添加属性和方法

当前模块对象会有一些初始化参数,可以理解为我们自己定义的全局变量。我们将这些参数写进构造函数中。

        var something = function(){
           this.passwordVal = null;
           this.nameVal = null;
        };

将其他用到的函数写入原型中。

something.prototype = {
        _requestIfTelregisted: function () { // 验证手机号是否注册接口
            var _data = {
                "registNum": this.nameVal
            };
            var nt = this.nTip;
            var that = this;
            $.ajax({
                type: "GET",
                url: "/cloudlink-core-framework/login/isExist",
                contentType: "application/json",
                data: _data,
                dataType: "json",
                success: function (data, status) {
                    var res = data.rows.isExist;
                    if (res == 0) {
                        nt.text('账号未注册');
                        utils.zhugeTrackForFailed(that.nameVal,'账号未注册');
                        return false;
                    } else {
                        that._requestData();
                        return true;
                    }
                }
            });
        },
    }

6.抽离工具类(对象)

例如:

    var utils = {
        hide:function(ele){ //元素的显隐
            $(ele).addClass('hidden'); 
        },
        show:function(ele){
            $(ele).removeClass('hidden'); 
        },      
        zhugeTrackForFailed: function (tel, sRsn) { //诸葛埋点
            if (zhugeSwitch == 1) {
                zhuge.track('登陆失败', {
                    '手机号': tel,
                    '原因': sRsn
                });
            }
        },
    };

7.执行构造函数

可以选择是否把类或new出的对象暴露出去。

    //global.something = something; 选择是或否暴露

    $(function() {
        global.somethingObj = new something(); //暴露出对象,供其他使用
        //new something(); 直接执行
    }); 

8.最终结构

(function (global, $, doc, lsObj, zhugeSwitch, zhuge) {
    'use strict';

    var something = function(){ 
        this.eventsMap = {
            'focus .name input': 'nameFocus',
        };
        this.initializeElements();
        this.initialization();      
    };

    something.Eles = {     
        password: '.password',      
    };

    var utils = {
        zhugeTrackForFailed: function(tel, sRsn) {
            if (zhugeSwitch == 1) {
                zhuge.track('登陆失败', {
                    '手机号': tel,
                    '原因': sRsn
                });
            }
        },      
    };

    something.prototype = {
        constructor: something,
        initialization: function() {
            this.bindEvent();
        },
        initializeElements: function() {
            var eles = loginClass.Eles;
            for (var name in eles) {
                if (eles.hasOwnProperty(name)) {
                    this[name] = $(eles[name]);
                }
            }
        },
        bindEvent: function() {
            this.initializeOrdinaryEvent(this.eventsMap);
        },
        unbindEvent: function() {
            this.uninitializeOrdinaryEvent(this.eventsMap);
        },
        initializeOrdinaryEvent: function(maps) {
            this._scanEventsMap(maps, true);
        },
        uninitializeOrdinaryEvent: function(maps) {
            this._scanEventsMap(maps);
        },
        _scanEventsMap: function(maps, isOn) {
            var delegateEventSplitter = /^(\S+)\s*(.*)$/;
            var type = isOn ? 'on' : 'off';
            for (var keys in maps) {
                if (maps.hasOwnProperty(keys)) {
                    if (typeof maps[keys] === 'string') {
                        maps[keys] = this[maps[keys]].bind(this);
                    }
                    var matchs = keys.match(delegateEventSplitter);
                    $('body')[type](matchs[1], matchs[2], maps[keys]);
                }
            }
        },      
        destroy: function() {
            this.unbindEvent();
        }       

    }

    //global.something = something; 选择是或否暴露

    $(function() {
        global.somethingObj = new something(); //暴露出对象,供其他使用
        //new something(); 直接执行
    });    

})(this, this.jQuery, document, lsObj, zhugeSwitch, zhuge);
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值