YUI经验谈 - 自定义事件默认行为
縱觀主流JS庫和框架,YUI在自定義事件方面做的尤為出色。如果需要挑出一個代表性的feature,那么非事件默認行為莫屬。
是什么
YUI自定義事件在總體上模仿了DOM事件的設計思想。DOM中的一些事件是有默認行為的,詳細見DOM3 Event - Default actions and cancelable events一節。簡單來說,所謂默認行為,是指該事件在通常情況下所表現出來的動作,例如:
- 一個鏈接節點的click事件,默認行為是轉向該鏈接href屬性對應的地址
- 表單的submit事件,默認行為是將表單包含的數據提交給表單的action
說通常情況下,是因為有時開發者會在事件的回調函數中調用
e.preventDefault();來阻止默認行為的發生。
YUI自定義事件遵循了同樣的思路,甚至API也和DOM完全一致。
有啥用
事件默認行為,本質上,是一種管理事件和行為的對應關系的機制。這種機制既不像回調那樣死板,也不像消息那樣開放。通過將通用處理邏輯作為事件默認行為,滿足常見需求的同時,為定制化需求提供了一定開放性,整體上更加靈活。
在DOM事件中,和默認行為相關的場景并不少見:
- 監聽到鏈接的click事件時,在鏈接地址中加入追蹤參數,利用默認行為跳轉到新地址
- 阻止表單submit事件默認行為,改為異步提交表單,提供更好的用戶體驗
在自定義事件的應用中,也會遇到一些類似的例子。例如:
- 注冊時,有一些郵箱雖然是可用的,但對于EDM不給力,在這種情況下,阻止表單項驗證成功的默認行為,展示建議用戶使用其它郵箱的提示
- 表單驗證組件在檢查表單項失敗后觸發failure事件,對應的默認行為是在表單項下方顯示錯誤信息。這樣的處理在大部分情況下是完全OK的。不過有一天,交互設計師在一個特定場景下提出所有提示都應該放在整個表單頂部,得益于這種靈活的機制,實現這種定制化邏輯十分輕松
- 字符計數插件在輸入變化時會默認更新字符數提示。在評價內容中,有更復雜的提示邏輯和展示效果,這時阻止默認行為,實現定制化內容即可
怎么用
下面以表單項驗證組件為例,展示如何使用事件默認行為。
首先創建FieldValidator組件,并使其具備EventTarget的功能,實現自定義事件機制:
var FieldValidator = function (ndField, validateFn) {var instance = this;// ... }; Y.augment(FieldValidator, Y.EventTarget);使用publish聲明檢查成功和失敗的自定義事件,主要目的是定義事件的默認行為:
var FieldValidator = function (ndField, validateFn) {// ...// 聲明檢查成功事件,設置默認行為instance.publish('success', {emitFacade: true,defaultFn: function (e) {e.field.next('.tip').setHTML('ok');}});// 聲明檢查失敗事件,設置默認行為instance.publish('failure', {emitFacade: true,defaultFn: function (e) {e.field.next('.tip').setHTML('error');}}); };接下來注冊表單項的focus、blur事件,在blur觸發時檢查表單內容,并觸發自定義事件:
var FieldValidator = function (ndField, validateFn) {// ...ndField.on({focus: function (e) {ndField.next('.tip').setHTML('');},blur: function (e) {if (validateFn(this.get('value'))) {// 檢查通過,觸發檢查成功事件instance.fire('success', { field: ndField });} else {// 檢查未通過,觸發檢查失敗事件instance.fire('failure', { field: ndField });}}}); };現在就可以使用這個組件了,一般情況下,我們不需要阻止默認行為,下面是一個具體示例:
// 檢查郵箱 new FieldValidator(Y.one('[name="email"]'), function (value) {return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(value); });一切看起來都很美,直到有一天你接到一個需求:Yahoo郵箱在檢查通過時需要展示EDM不給力的提示,這時候默認行為就可以來拯救你了:
var validator = new FieldValidator(Y.one('[name="email"]'), function (value) {return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(value); }); validator.on('success', function (e) {if (e.field.get('value').indexOf('@yahoo.com') !== -1) {// 阻止默認行為e.preventDefault();// 定制化行為e.field.next('.tip').setHTML('換個郵箱吧,yahoo.com郵箱收不到優惠通知哦');} });在success事件的回調中,通過阻止默認行為,不再執行提示內容為OK的默認邏輯,而是切換成判斷雅虎郵箱,并給出特定提示的定制化邏輯。
完整代碼展示,請移步JSFiddle。
要注意
一個好的idea,最容易被濫用。默認行為不是萬能藥,只適合一些這樣的場景:
- 需要通過事件進行消息廣播。如果callback就可以解決問題,那么明智之舉是使用callback
- 存在定制化需求的預期,即有些情況下需要中止默認行為的發生,換之以定制化行為
參考
- DOM3 Event - Default actions and cancelable events
- YUI EventTarget
總結
以上是生活随笔為你收集整理的YUI经验谈 - 自定义事件默认行为的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 降低软件复杂性一般原则和方法
- 下一篇: Redis 高负载下的中断优化