自定义事件是一种处理与DOM产生交互的代码逻辑片段之间耦合的很好的架构方法。
一个简单的jQuery插件——选项卡
让ul列表来响应点击事件。当用户点击一个列表项时,给这个列表项添加一个名为active的类,同时将其他列表项中的active类移除:
<ul id="tabs"> <li data-tab="users">users</li> <li data-tab="groups">groups</li> </ul> <div id="tabsContent"> <div data-tab="users">uuuuuuuuuu</div> <div data-tab="groups">ggggggggg</div> </div>
一般处理方式
jQuery.fn.tabs = function(control) { var $tabs = $(this), $control = $(control); $tabs.find('li').click(function() { // 从列表项中删除和添加active类 $tabs.find('li').removeClass('active'); this.className = 'active'; // 对应内容的显示 var tabName = $(this).attr('data-tab'); $control.find('[data-tab]').hide(); $control.find('[data-tab="' + tabName +'"]').show(); }); // 初始化状态 $tabs.find('li:first').addClass('active'); // 选中选项卡 $control.find('>[data-tab]').hide().first().show(); // 只显示第一个div return this; };
现在看上去插件没有什么问题。但可以做下列优化:我们给所有的列表项都添加了click事件回调,可以用事件委托来优化它;点击事件回调的实现很臃肿,很难一眼看出发生了什么;最后,如果另一个开发者想要扩展这个插件,他很可能会将其重写。
优化后的代码
使用自定义事件让代码变得更加整洁。
在点击选项卡时触发一个change.tabs事件,并绑定若干回调方法来适当修改active类。
// 自定义事件tabs.change // 缓存选项卡元素,减少DOM直接查找 jQuery.fn.tabs2 = function(control) { var $tabs = $(this), $control = $(control), $lis = $tabs.find('li'); // 利用事件委托,监听单击选项卡事件 $tabs.on('li', 'click', function() { // 单击的选项卡的data-tab属性值 // var tabName = $(this).attr('data-tab'); var tabName = this.getAttribute('data-tab'); // 自定义属性需要用getAttribute()获取 // 在单击时触发自定义事件 $tabs.trigger('change.tabs', tabName); }); // 绑定自定义事件 // 解耦回调函数,易扩展 $tabs.bind('change.tabs', function(e, tabName) { $lis.removeClass('active').filter('[data-tab="'+ tabName +'"]').addClass('active'); }); $tabs.bind('tabs.change', function(e, tabName) { $control.find('>[data-tab]').hide(); $control.find('>[data-tab="'+ tabName +'"]').show(); }); // 初始化状态 var firstName = $lis.first().attr('data-tab'); $tabs.trigger('tabs.change', firstName); return this; };