使用JavaScript的简单事件系统(ES5) - JS自定义事件

时间:2015-09-07 10:04:40

标签: javascript events dom event-handling dom-events

说明:

  1. 使此代码无需以任何方式修改代码段。
  2. 仅使用普通的旧JavaScript而不使用第三方库。
  3. 编写新代码,使下面的代码能够正常工作。
  4. 提示:随意扩展本机对象......即使这通常是一种不好的做法。

    // Start with an object, any object
    var myObject = {};
    
    
    // Register an event on your object using
    // an `on` method
    myObject.on('myEvent', function(data) {
        // Log the data passed to the callback
        console.log(data);
    });
    
    // Trigger the event using a `trigger` method.
    // Include some data when you trigger the event.
    myObject.trigger('myEvent', {
        company: 'ABC Corp',
        location: 'WTC Bangalore, IN',
        website: 'http://abc.co'
    });
     
    // Register a different event
    myObject.on('yourEvent', function() {
        console.log('yourEvent fired');
    });
    
    // Trigger the new event
    myObject.trigger('yourEvent');
    
    // Trigger all existing events using a special
    // "star" identifier.
    myObject.trigger('*');
    
    // Remove one event by name
    myObject.off('myEvent');
    
    // Since we've removed the event, this should
    // do nothing
    myObject.trigger('myEvent');
    
    // Remove all existing events
    myObject.off();
    
    // Since we've removed all events, this should
    // do nothing
    myObject.trigger('*');

    其他一切进展顺利。在实施myObject.trigger("*")时,我无法得到“论据”;在实现"*"时无法读取参数对象/参数,因此抛出undefined

    My JSFiddle

2 个答案:

答案 0 :(得分:3)

声明 我显然不知道你去哪所学校或什么,但请不要欺骗自己欺骗你的老师。通过几个简单的问题,他们会知道你是否理解了这些材料,如果你出现了一个很好的答案,但没有知识来支持它,他们就会知道是什么。我并没有指责你这一点,只是对去年毕业后与老师有良好关系的人的友好建议;)

那么,我们该怎么做呢?基本上,您必须为object的原型添加一些功能,至少如果您希望这会影响之后制作的所有对象。如果您只希望该类具有此功能,您始终可以创建自己的类并将该函数添加到该原型中。

我们需要在原型中添加3个函数,onofftrigger当然。最重要的是,我们添加了一个名为events的额外属性,最初是一个空对象。 你可以在jsfiddle中查看所有这些的原始代码,我只会在这里查看代码的结构和逻辑。

events将包含与每个事件关联的所有处理程序(函数)。在第一次添加事件时,我们向eventName对象添加events属性,此属性的值最初是一个空数组。

on将在eventName中找到(或创建)链接到events的数组,并将该函数推入数组(注意我们此时不调用该函数,我们只需将对函数的引用存储在数组中。

off将迭代eventName数组,如果找到相同的函数(请注意===),请将其从数组中删除。

trigger将迭代eventName的数组并调用每个函数。请注意,函数在对象的函数集中使用this关键字调用,并且调用了与trigger函数相同的参数(eventName除外,第一个参数被过滤掉) 。是的,这意味着您可以传递任意数量的参数来触发(),并将它们全部传递给每个处理程序。

我不会详细说明spliceslice===argumentsapply之类的内容,我相信你可以在世界各地的互联网上找到更多更好的信息。

你可以为此做更多的事情,比如通过一些很好的范围使用来使events对象不可见,但这不是问题的一部分所以我没有打扰它。

如果您在查看完之后还有其他问题,请随时提出。我也没有广泛测试,如果你发现任何错误,请告诉我。

编辑:我最初没有阅读评论,但我现在还添加了对'*'通配符的支持。基本上,函数现在检查通配符,并在删除或触发时迭代eventName对象上的所有event。您也可以通过不提供函数或提供相同的通配符来删除事件的所有函数,但使用eventName。

EDIT2:有一些错误运行教师的代码,意识到我在迭代时忘了检查hasOwnProperty。看一下,在使用原型时非常重要! 我现在在我的jsfiddle中输入老师的代码,告诉你它有效:)

jsfiddle with own code

jsfiddle with teacher code

EDIT3 - 关于'未定义'日志。

教师的代码调用.trigger 5次,你应该看到4个控制台日志,据我所知,它们都是正确的。让我浏览每个触发器,并且后续的控制台日志。

  1. 您向myEvent添加处理程序,该处理程序记录第一个参数
  2. 您使用参数 =>触发myEvent参数(对象)是 登录。
  3. 您向yourEvent添加处理程序,该处理程序记录硬编码 字符串。
  4. 您触发yourEvent,无参数=>硬编码字符串已记录为“
  5. 您触发* 没有参数,所有处理程序运行=>记录undefined,因为没有给出参数,data的处理程序中的myEvent是未定义的。硬编码字符串也会被记录
  6. 删除myEvent处理程序,触发myEvent并确认没有调用任何函数
  7. 删除所有事件处理程序,触发*并确认没有任何事件调用任何函数。
  8. 老实说,我不知道你在第5步会发生什么,因为你没有给出任何参数,data被分配了undefined,这是预期的行为。

    如果要合并步骤2中给出的数据,使其保留在对象上,请在处理程序中指示。 (例如,迭代data的所有属性并将其添加到this,然后记录this)。现在你只需传递数据,就会记录下来,然后扔掉。您还可以在步骤5中添加一个参数,然后所有处理程序都会接收它(包括yourEvent处理程序,但是那个不分配也不使用它。)

答案 1 :(得分:0)

document.getElementById("myBtn").addEventListener("click", displayDate);