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


    Event Handling

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

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

         虽然由childparent发送事件是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冒泡事件的函数。例如:

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

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

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

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

    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

    }

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

    DOM (and DOM-like) Events

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

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

         除了target属性外,enyo指定了dispatchTarget属性来设置包含event targetenyo 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)。这些事件大部分都是跨平台的,所以客户端代码不必区分touchmouse事件接口。

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

    Signals

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

         Enyo.Signals提供了绕过正常组件树来广播和订阅全局信息的方法。在enyo框架内部,DOM事件没有目标节点作为signal来传播。这些事件包括windows event,如onloadonbeforeunload,还有直接从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时调用该方法。例如:

     1 enyo.kind({
     2     name: "Receiver",
     3     components: [
     4         // 'onTransmission' is the message name and 'transmission' is the
     5         // name of a handler method in my owner.
     6         {kind: "Signals", onTransmission: "transmission"}
     7     ],
     8     transmission: function(inSender, inEvent) {
     9         // respond to the signal
    10     }
    11 });

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

    enyo.Signals.send("onTransmission");

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

    一些需要注意的地方:

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

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

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

         不要滥用Signals。对象与全局通信耦合是非常糟糕的。

  • 相关阅读:
    method-r
    dtrace
    轻用其芒,动即有伤,是为凶器;深藏若拙,临机取决,是为利器!
    Git---报错:git Please move or remove them before you can merge 解决方案
    Git----拉取远程分支,git pull,git rebase,git pull --rebase的区别
    Git----查看提交日志
    Git---tag
    Git----常见工作管理总结
    【线上监控】日志上报bug处理方式总结
    接口文档所需内容
  • 原文地址:https://www.cnblogs.com/waimai/p/2853653.html
Copyright © 2020-2023  润新知