Query 插件的实现深受自定义事件机制的影响,同样,自定义事件也是处理与DOM 产生交互的代码逻辑片段之间耦合的很好的架构方法。
当你想给你的应用添加一个功能片段时,或许经常纠结于是否应当将这个片段抽离为一个插件。自定义事件的思路可以帮你做这种解耦,并逐渐形成一个可复用的库。
比如,我们来看一个简单的jQuery 插件——选项卡。我们让ul 列表来响应点击事件。当用户点击一个列表项,给这个列表项添加一个名为active 的类,同时将其他列表项中的active 类移除:
1 2 3 4 5 6 7 8 |
|
另外,id 为tabsContent 的div 用来存放每个选项卡对应的实际内容。根据当前激活的选项卡,来对应地给div 的子节点添加或删除active 类。实际的显示和隐藏选项卡和内容都由CSS 来控制,我们的插件仅仅处理active 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
插件位于jQuery 的prototype 里,因此可以基于jQuery 实例来调用:
$("ul#tabs").tabs("#tabContent");
现在看上去插件有什么问题吗?没错,我们给所有的列表项都添加了click 事件回调,这是第1 个错误。我们可以使用上文提到的delegate() 来优化代码。同样,点击事件回调的实现很臃肿,很难一眼看出发生了什么。除此之外,如果另一个开发者想要扩展这个插件,他很可能会将其重写。
我们来看下如何使用自定义事件让代码变得更整洁。在点击选项卡时触发一个change.tabs 事件,并绑定若干回调方法来适当修改active 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
我们看到使用自定义事件回调可以让代码更加整洁。这也意味着选项卡状态切换回调彼此分离,这也让插件代码更具扩展性。比如我们可以在程序中直接更改选项卡的状态,只需触发被观察列表的change.tabs 事件即可:
$("#tabs").trigger("change.tabs", "users");
同样,我们可以将切换选项卡的动作和窗口的hash 做关联,这样就可以使用浏览器的后退按钮了:
1 2 3 4 5 6 7 |
|
发表回复