利用javascript自定义事件机制解耦

模块化始终是提升项目代码可维护性的首选,各个语言实现模块化的具体方式都有一些差别。在javascript当中,可以利用Object来实现页面功能块的模块化。

比如,页面上有一块表格内容用于显示一条一条的用户数据,然后最后一列是“修改”、“删除”操作,那么这个功能块可以大致写成如下结构:

var userTable = {
    init: function(params) {
        // 初始化功能块(参数调整、渲染界面样式、缓存DOM节点、填充数据、绑定事件等等)
        this._renderData(this._data);
        this._bindEvent();
    },
    _bindEvent: function() {
        // 绑定事件(修改、删除等等)
    },
    _renderData: function(data) {
        // 填充数据
    }
};

如上代码,在DOM ready的时候,就可以直接调用userTable.init()来展示这个功能块了。

但是,这里有两个问题还没解决:

对于第一个问题,解决很简单,userTable直接向外部提供API即可,此时代码如下:

var userTable = {
    init: function(params) {
        // 初始化功能块(参数调整、渲染界面样式、缓存DOM节点、填充数据、绑定事件等等)
        this._renderData(this._data);
        this._bindEvent();
    },
    _bindEvent: function() {
        // 绑定事件(修改、删除等等)
    },
    _renderData: function(data) {
        // 填充数据
    },
    /**
     * 为外部提供的API,用于刷新当前用户功能块的数据
     */
    refresh: function() {
        // 刷新用户数据
    }
};

对于第二个问题,则是借助于事件机制了。这种事件机制其实在很多框架或库中都有实现(jquery、backbone等),此处暂且实现一个小型的事件机制

在eventDealer对象中,有基本的on、trigger、off方法,分别用于注册事件、触发事件、取消注册事件。

借助于eventDealer,该功能区的代码可升级为:

var userTable = Object.create(eventDealer, {
    init: function(params) {
        // 初始化功能块(参数调整、渲染界面样式、缓存DOM节点、填充数据、绑定事件等等)
        this._renderData(this._data);
        this._bindEvent();
    },
    _bindEvent: function() {
        // 绑定事件(修改、删除等等)
        var _this = this;
        this._modifyNode.on('click', function() {
            // 执行修改操作(访问后端接口之类的)
            // 在修改操作完成之后(此处可能会涉及到异步回调,请读者自己留意下)
            _this.trigger('modified', data);
        });
    },
    _renderData: function(data) {
        // 填充数据
    },
    /**
     * 为外部提供的API,用于刷新当前用户功能块的数据
     */
    refresh: function() {
        // 刷新用户数据
    }
});

userTable继承自eventDealer,然后自然就有了eventDealer的能力。同时,以上代码在_bindEvent函数中,完成修改操作之后,调用了trigger方法,触发了modified事件,如果外部对这个事件感兴趣,则可以事先注册相应的回调函数:

userTable.on('modified', function(data) {
    // do something
});

由此,两个问题得到了解决,用户功能块与外部耦合度就很低了。

blog comments powered by Disqus