您的位置:首页 > 其它

enyo官方开发入门教程翻译一Key Concepts之Event Handling

2013-01-09 21:01 603 查看
Event Handling

Enyo采用了消息传递策略来间接地在不同组件之间通信。我们把这些信息作为事件,这与常见的DOM用法一直。一般事件按照child-parent顺序在组件树中冒泡。在使用dom包时,DOM事件和自定义事件是一致的。

使用事件的关键在于component组件设计的封装。大部分时候,一个component的children不应当知道他们的父类。所有child发出的事件应当由父类决定是否处理而不应在child中调用父类的方法处理事件。

虽然由child向parent发送事件是enyo的标准,但在一些情况下这种实现模式效率低下且代码笨拙。因此enyo还提供了另一种通信方法---enyo.Signals ,文章后面会提到该方法。

Sending Events

Component组件使用events语句块来声明它发送的事件:

events: {

onStateChanged:""

}

注意,为了方便 事件的名称总是以“on”开头。

对于每一个在component组件的event语句块中注册过的事件,都会在该kind上创建一个helper函数do<EventName>,component组件可以调用该方法来发送事件到component组件树。这个函数接受一个可选的inEvent参数,该参数可以包含特定的事件信息并传递给处理函数。例如要从上面的例子中发送“onStateChanged”事件,一个组件要调用

this.doStateChanged(newState) // parameter is specific to the "onStateChanged" event

在内部,do<EventName>函数包装了enyo原始的发送事件组件树的冒泡函数。

this.bubble(inEventName <, inEvent, inSender>)

inEventName是包含on前缀的事件名称

inEvent是可选的对象,它包含特定的事件信息,必须是js对象不能使原始的对象。

inSender 该参数应该总是省略掉,尽管你可以用它来为接下来的处理函数强制指定一个特定的sender。

注意:声明一个event块使用do<EventName>helper函数能够更好的直接调用冒泡函数,event语句块有更好的描述性并且更好的定义了kind的接口。

Creating Handlers

事件的处理程序是捕捉children冒泡事件的函数。例如:

myEventHandler: function(inSender, inEvent) {
// Can return true to indicate that this event was handled and
// propagation should stop
}


这个处理函数可以返回一个为真的结果来阻止event事件的传播。否则,它会继续从component组件树中传播。

注意,返回真值的方法与传统的DOM协定不同(返回值将决定默认的action是否会发生)。如果你需要控制DOM事件的默认action,使用现代版的inEvent.preventDefault()。inEvent.preventDefault()不会阻止enyo事件的冒泡,从处理程序返回true能阻止冒泡。

因为在停止前事件一直冒泡,事件的sender可能与原始的sender不同。事件的处理程序可以用inEvent.originator来获取原始的组件。例如,点击一个按钮,按钮发出一个onclick事件,沿control链冒泡,经由父类冒泡到祖父类。从祖父类来看,事件发起源是button事件的sender是button的父类。

Attaching Handlers to Events

在组件中有两种通用的处理事件的方式。第一种:

components: [

{name: "thing", ontap: "thingTap"}

],

thingTap: function(inSender, inEvent) {

// do stuff

}

第二种:

handlers: {

ontap: "anythingTap"

},

anythingTap: function(inSender, inEvent) {

// do stuff

}

如果你同时使用这两种事件处理策略,你会在两处都接收到event。你可以在tingTap中阻止冒泡来避免这一情况。例如:

components: [

{name: "thing", ontap: "thingTap"}

],

handlers: {

ontap: "anythingTap"

},

thingTap: function(inSender, inEvent) {

// taps on _thing_ will bubble up to _anythingTap_ also,

// unless I stop propagation here

return true; // handled here, don't propagate

}

anythingTap: function(inSender, inEvent) {

// do stuff

}

如果你需要处理更复杂的程序,可以使用inSender和inEvent.originator属性来帮助辨别事件的出处。

DOM (and DOM-like) Events

在enyo中,DOM事件可以一直冒泡到document被enyo.dispatcher处理。Dispatcher决定事件发送到哪里并为不同的事件处理程序提供插件接口。

只要有可能,dispatcher就会避免原始的DOM事件。为了强制阻止DOM事件冒泡,你可以从事件的处理方法中返回true。

除了target属性外,enyo指定了dispatchTarget属性来设置包含event target的enyo control。

下面的DOM事件由enyo处理:

mousedown

mouseup

mouseover

mouseout

mousemove

click

dblclick

change

input

keydown

keyup

keypress

resize

load

unload

message

如果你希望enyo处理额外的DOM事件(如mousewheel),这样做:

document.onmousewheel = enyo.dispatch;

除了DOM事件,还有一些常规的输入事件,dispatcher会把它们作为类DOM事件发送(如ontap, ondown, onup, ondragstart, ondrag, ondragfinish, onenter, 和 onleave)。这些事件大部分都是跨平台的,所以客户端代码不必区分touch和mouse事件接口。

由于一些约定,DOM事件和类DOM事件在作为enyo事件时仍然保持小写,但是在enyo kind中声明的事件使用驼峰式大小写(如onStateChanged)。关于类DOM事件的更多信息请参考 User Input

Signals

在你的应用中有时两个不相关的组件可能需要通信。如果使用标准的event模型,你将把事件传递给一个公共父类(最坏的情况是传递到app的顶级kind)然后将事件返回给目标组件。由于这样需要大量的plumbing,enyo提供了替代选项。

Enyo.Signals提供了绕过正常组件树来广播和订阅全局信息的方法。在enyo框架内部,DOM事件没有目标节点作为signal来传播。这些事件包括windows event,如onload和onbeforeunload,还有直接从document发出的事件如当document获得焦点时的onkeypress事件。Signal对于连接非enyo事件并使用application代码中的enyo kind处理这些事件也很有用。

为了广播信息,sender只要调用enyo.Signals的静态send函数即可:

enyo.Signals.send(inEventName, inEvent);

为了监听signal,组件需要在它的components语句块中包含Signals实例。需要通过设置Signals对象的messageName属性为"Signals"来指定处理方法。当收到messageName signal时调用该方法。例如:

enyo.kind({
name: "Receiver",
components: [
// 'onTransmission' is the message name and 'transmission' is the
// name of a handler method in my owner.
{kind: "Signals", onTransmission: "transmission"}
],
transmission: function(inSender, inEvent) {
// respond to the signal
}
});


可以这样调用该函数来处理signal事件:

enyo.Signals.send("onTransmission");

注意,和所有的enyo信息处理方法一样,signal处理函数接收两个函数:一个发送信息的组件的引用和一个事件信息的包装类

一些需要注意的地方:

传递给send方法的signal名称必须配置接收Signals的message名称,都必须包含on前缀

所有注册了特定message的signals实例都会接收message

Send方法在enyo.Signals本身内部,不是Signals的实例。

不要滥用Signals。对象与全局通信耦合是非常糟糕的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: