用JavaScript编写自定义事件调度程序?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用JavaScript编写自定义事件调度程序?相关的知识,希望对你有一定的参考价值。

如何在javascript中向我自己的类的对象添加事件侦听器和调度事件? 在ActionScript 3中,我可以简单地从Sprite / DisplayObject继承并使用那里可用的方法。像这样:

// ActionScript-3:
// I can add event listeners to all kinds of events
var mySprite: Sprite = new MySprite();
mySprite.addEventListener("my_menu_item_click", onMenuItemClick);

// later I can dispatch an event from one of my objects
mySprite.dispatchEvent(new Event("my_menu_item_click", ...));

我希望在JavaScript中也一样。到现在为止我知道window.addEventListener(...)document.addEventListener(...)。到目前为止,我在JavaScript中有自己的Sprite类,我想用它来发送我自己的事件。

// JavaScipt:
function Sprite()
{
    this.x = 0;
    this.y = 0;
    // ...
}

由于这两种语言看起来与事件“相似”,我想我需要继承某些类?或者我是否必须使用一些全局变量,如窗口和/或文档?

我在这里使用html5。我只有1个画布和一堆精灵被吸引到用户输入。我想要一个精灵A来订阅另一个精灵B的事件。但是不要给第三个精灵C.

答案

我试图将方法添加到我的Sprite类中并成功。 当然还没有完成,但至少它是有效的。 这就是我在寻找的东西。

function Sprite()
{
    // ...
    this.eventListeners = new Array();

    this.addEventListener = function(type, eventHandler)
    {
        var listener = new Object();
        listener.type = type;
        listener.eventHandler = eventHandler;
        this.eventListeners.push(listener);
    }

    this.dispatchEvent = function(event)
    {
        for (var i = 0; i < this.eventListeners.length; i++)
            if (event.type == this.eventListeners[i].type)
                this.eventListeners[i].eventHandler(event);
    }
}
另一答案

你可以制作自己的,这个是通用的,非常简单。我实际上自己用它:D

这是您将获得的功能。

  • 使用addEventListener()
  • removeEventlistener()
  • dispatchEvent()(或者您希望调用它)

这个函数将向对象添加所需的方法,同时返回一个可以调度事件的函数。

// Snippet  =========================================
function createEventDispatcher(o) {
  var L = o.__listeners = {};
  o.addEventListener = function(n, fn) { L[n] = L[n] || []; L[n].push(fn); };
  o.removeEventListener = function(n, fn) { var a = L[n]; for (var i = 0; i < a.length; i++) if (a[i] === fn) a.splice(i, 1);};
  return function() { var a = Array.prototype.slice.call(arguments); var l = L[a.shift()]; if (l)  for (var i = 0; i < l.length; i++) l[i].apply(l[i], a)};
}

:

// Simplified example of usage =========================================
function App(){
    // Add functionality
    var dispatchEvent = createEventDispatcher(this); // Call snippet

    // Use functionality
    var count = 0;
    setInterval(function(){ 
        dispatchEvent("something",{msg:"hello",count:count++});
    },100);
}();

// Somewhere outside your App    
    function onSomething(event){
        console.log(event.msg + "["+event.count+"]");
        if(event.count >= 10){ 
            // Remove eventlistener 
            myApp.removeEventListener("something",onSomething);
        } 
   }

    var myApp = new App();    
    myApp.addEventListener("something",onSomething);

// Easy

https://jsfiddle.net/squadjot/0n2nby7k/

如果要从对象中删除所有侦听器,可以执行类似的操作。

myApp.__listeners = {};
另一答案

您可以使用Event和CustomEvent对象在JS中执行相同的操作:

var event = new Event('build');

// Listen for the event.
elem.addEventListener('build', function (e) { ... }, false);

// Dispatch the event.
elem.dispatchEvent(event);

资料来源:MDN(https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

另一答案

这是某种“功能”方法,我不喜欢在javascript中使用“new”和“this”。我喜欢普通的,同行的或扩展的物体。

// Some helper functions, should be imported from a different file
const partial = fn => (...pargs) => (...args) => fn.apply(null, [...pargs, ...args]);
const partialRight = fn => (...pargs) => (...args) => fn.apply(null, [...args, ...pargs.reverse()]);

// Module starts here
const on = (listeners, type, listener, once) => {
  if (!listeners[type]) {
    listeners[type] = [];
  }
  if (listeners[type].indexOf(listener) < 0) {
    listener.once = once;
    listeners[type].push(listener);
  }
};

const once = partialRight(on)(true);

const off = (listeners, type, listener) => {
  const listenerType = listeners[type];
  if (listenerType && listenerType.length) {
    const index = listenerType.indexOf(listener);
    if (index !== -1) {
      listenerType.splice(index, 1);
    }
  }
  if ((listenerType && !listenerType.length) || !listener) {
    delete listeners[type];
  }
};

const emit = (listeners, type, ...data) => {
  if (listeners[type]) {
    listeners[type].forEach(listener => {
      listener.apply(null, data);
      if (listener.once) {
        off(listeners, type, listener);
      }
    });
  }
};

// you could use "export default () => {}" to make it an importable module
const eventEmitter = () => {
  const listeners = {};
  return {
    on: partial(on)(listeners),
    once: partial(once)(listeners),
    off: partial(off)(listeners),
    emit: partial(emit)(listeners),
  };
};

const myObj = Object.create(Object.assign({}, eventEmitter()));

myObj.on('hello', name => console.log(name));

setTimeout(() => {
  myObj.emit('hello', 'Csaba')
}, 2000)

以上是关于用JavaScript编写自定义事件调度程序?的主要内容,如果未能解决你的问题,请参考以下文章

组件的调度自定义事件没有父级

使用 angularjs 在 kendo 调度程序上自定义删除确认弹出窗口

Magento 调度自定义事件不起作用

Flex 4 从自定义组件调度自定义事件(为啥 flex 将自定义事件转换为 mouseevent)

事件调度程序通知[关闭]

如何以编程方式为 Kendo Ui 调度程序调用导航事件