出家如初,成佛有余

bubbling-library:YUI Extension for Event-Driven Applications研究

Posted in Uncategorized by chuanliang on 2007/09/23

基于YUI 的YUI Bubbling Library最近发布了新版本,YUI Bubbling Library使用了Observer pattern (publish/subscribe pattern)

Observer-pattern-uml

Observer设计模式

1、DOM Event Model

W3C DOM Level2的事件模型规范中,事件在DOM树中的传播过程(从根节点到目标节点)被分为了三个阶段:捕捉(Capture)、冒泡(Bubbling)、目标(Target)。Dom 事件触发后从Root根节点自上而下传播事件到 target 对象(此过程称为 Capture Phase),然后传播事件给 target 对象(此过程称为 Target Phase),最后在自下而上的传播事件(此过程称为 Bubbling Phase)。

eventflow

一些有关DOM Event Model的资料:

  • brainjar.com的The DOM Event Model

http://www.brainjar.com/dhtml/events/

http://www.brainjar.com/dhtml/intro/

  • W3C Document Object Model Events

http://www.w3.org/TR/DOM-Level-2-Events/events.html

  • Opera Event capture explained

http://dev.opera.com/articles/view/event-capture-explained/

  • Mozilla DOM Event Reference

http://www.mozilla.org/docs/dom/domref/dom_event_ref.html

  • Wikipedia DOM Events

http://en.wikipedia.org/wiki/DOM_Events

2、DOM事件模型处理方法

事件模型的处理需要解决两个关键方面:

    • 把一个事件和 HTML 元素绑定起来的方法。
    • 在事件被触发后如何对之进行处理。

在apple开发人员联盟站点上有一篇文档“同时支持三种事件模型“对此讲述得很清晰和全面透彻。

    • 事件绑定的方法

事件绑定是指构造一个响应系统或者用户动作的 HTML 元素的过程。在不同的浏览器版本中,有不少于五种事件绑定技术。

事件绑定方法I:绑定元素属性
<SCRIPT LANGUAGE="JavaScript">
function convertToUpper(textbox) {
    textbox.value = textbox.value.toUpperCase();
}
</SCRIPT>
...
<FORM ....>
<INPUT TYPE="text" NAME="first_name" onChange="convertToUpper(this)">
<INPUT TYPE="text" NAME="last_name" onChange="convertToUpper(this)">
...
</FORM>
事件绑定方法II:绑定对象属性
document.forms[0].myButton.onclick = myFunc;

使用此种绑定方法,在事件触发的时候,没有办法向事件函数传递参数

事件绑定方法III: 绑定 IE4+<SCRIPT FOR> 标识
事件绑定方法IV:使用 IE5/Windows 的 attachEvent() 方法

attachEvent() 方法的用法如下所示:

elemObject.attachEvent("eventName", functionReference);

eventName 参数的值是表示事件名称的字符串,比如 onmousedownfunctionReference 参数是一个不带括号的函数引用,和早些时候描述的事件属性方法中一样。

事件绑定方法V:使用 W3C DOM 的 addEventListener() 方法

addEventListener() 方法的语法如下所示:

nodeReference.addEventListener("eventType", listenerReference, captureFlag);

addEventListener() 方法为指定的结点注册了一个事件,表示该结点希望处理相应的事件。这个方法的第一个参数是一个声明事件类型的字符串(不带”on”前缀),比如 clickmousedown,和 keypressaddEventListener() 方法的第二个参数可以和早些时候描述过的函数引用同样对待。第三个参数则是一个 Boolean 值,指明该结点是否以DOM中所谓的捕捉模式来侦听事件。对于一个典型的事件侦听器来说,第三个参数应该为 false(假)

    • 访问事件对象

IE4+ 的事件对象是 window 对象的一个属性,也即需要通过window.event来判断事件类型。这也意味着在所有的实例中只有一个事件对象。

而对于 遵守W3C DOM的浏览器 来说,除了基于标识属性风格的绑定方法之外,其它绑定方法都是把事件对象自动传递给与事件相绑定的函数。传递给函数的是一个单一的参数。开发者需要在函数中定义一个参数变量,来“接收”该参数的值。为了避免和IE中的 window.event 对象互相冲突,请不要把参数命名为 event。举例来说,把它命名为 evt 就相当好。

兼容IE和W3C DOM事件对象引用

function myFunc(evt) {
    evt = (evt) ? evt : ((window.event) ? window.event : "")
    if (evt) {
        // process event here
    }
}
能够是被基于IE和W3C DOM事件后,由于DOM存在capture phase、target phase、bubbling phase,
在事件传播过程中涉及许多节点,文档中的每一个结点都可以接收事件,一个典型问题是要区分evt.currentTarget和
evt.target。

W3C DOM结点的事件目标

有两种策略,一个策略是使用 W3C DOM 事件对象的 currentTarget 属性,该属性返回一个处理事件的结点的引用。脚本中的决策树需要考虑这个属性。

function toggleHighlight(evt) {
    evt = (evt) ? evt : ((window.event) ? window.event : "")
    if (evt) {
        var elem
        if (evt.target) {
            if (evt.currentTarget && (evt.currentTarget != evt.target)) {
                elem = evt.currentTarget
            } else {
                elem = evt.target
            }
        } else {
            elem = evt.srcElement
        }
        elem.className = (evt.type == "mouseover") ? "highlight" : "normal"
    }
}

另一个可选的方法是考察由 target 属性返回的对象的 ronodeType 属性。一个能够把事件定向给文本结点的浏览器,也可以把一个文本结点的 nodeType 属性值报告为3,而不是报告为元素结点的类型(其值为1)。如果事件的目标是一个文本结点,则脚本程序就可以通过该文本结点的 parentNode 属性来得到其上级元素结点的引用。这种方法的决策树在某种程度上得到更多的改进:

function toggleHighlight(evt) {
    evt = (evt) ? evt : ((window.event) ? window.event : "")
    if (evt) {
        var elem
        if (evt.target) {
            elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target
        } else {
            elem = evt.srcElement
        }
        elem.className = (evt.type == "mouseover") ? "highlight" : "normal"
    }
}

一个事件处理函数的模板

// shared function
function getTargetElement(evt) {
    var elem
    if (evt.target) {
        elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target
    } else {
        elem = evt.srcElement
    }
    return elem

}

function functionName(evt) {
    evt = (evt) ? evt : ((window.event) ? window.event : "")
    if (evt) {
        var elem = getTargetElement(evt)
        if (elem) {
            // process event here
        }
    }
}

其他关于事件模型的一些资料:

    • 同时支持三种事件模型(中英文版本)

http://developer.apple.com/internet/webcontent/eventmodels.html

http://developer.apple.com.cn/internet/webcontent/eventmodels.html

    • Handling events with the DOM – Part I

http://www.devarticles.com/c/a/JavaScript/Handling-events-with-the-DOM-Part-I/

    • Handling events with the DOM – Part III

http://www.devarticles.com/c/a/JavaScript/Handling-events-with-the-DOM-Part-III/

    • DOM Design Tricks II

http://www.alistapart.com/stories/domtricks2/

    • Event handling in the DOM

http://www.javascriptkit.com/dhtmltutors/domevent1.shtml

3、Bubbling Library

Bubbling Library(http://www.bubbling-library.com/)的思想来源于Event-Driven Web Application Design

要使用Bubbling Library的用法,首先还要熟悉YUI Event.

关于Bubbling Library的使用可以其文档及如下资料:

http://yuiblog.com/blog/2007/09/13/bubbling-library-by-caridy/

  • 样例
  • Bubbling Library的适用场合
  • 与jQuery实现机制对比

4、参考资料

Apple中文开发站点的一些文档

http://developer.apple.com.cn/Documentation/InternetWeb/

Pro JavaScript Techniques第六章: 事件

http://bbs.blueidea.com/viewthread.php?tid=2745405&page=1#pid3215727

Learning jQuery

http://www.learningjquery.com/

Yahoo! UI Library: Event Utility

http://developer.yahoo.com/yui/event/

Event Delegation versus Event Handling

http://icant.co.uk/sandbox/eventdelegation/

Unobtrusive Javascript

http://www.onlinetools.org/articles/unobtrusivejavascript/

Technorati 标签: , , , , , ,

No Responses Yet

Subscribe to comments with RSS.

  1. chobbyVonna said, on 2009/04/24 at 18:49

    I’m the only one in this world. Can please someone join me in this life? Or maybe death…


发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: