使用 JavaScript (ES5) 的简单事件系统 - JS 自定义事件
Simple event system using JavaScript (ES5) - JS Custom Event
说明:
- 无需以任何方式修改代码段即可使此代码正常工作。
- 仅使用普通的旧 JavaScript,不使用第三方库。
- 编写新代码,使下面的代码能够正常工作。
提示:请随意扩展本机对象...尽管这通常是一种不好的做法。
// 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("*")
时无法获得 "arguments";实现 "*"
时无法读取参数对象/参数,因此抛出 undefined
.
document.getElementById("myBtn").addEventListener("click", displayDate);
免责声明
我显然不知道你上的是什么学校什么的,但请不要试图愚弄你的老师来愚弄自己。通过几个简单的问题,他们就会知道您是否理解 material,如果您给出了一个很好的答案但没有支持它的知识,他们就会知道发生了什么。我不是指责你,只是去年毕业后与老师有良好关系的人的友好建议;)
那么,我们该怎么做呢?基本上,您必须向 object
的原型添加一些功能,至少如果您希望这会影响之后制作的 所有 对象。如果您只希望 class 具有此功能,您始终可以创建自己的 class 并将函数添加到该原型。
我们需要在原型中添加 3 个函数,当然是 on
、off
和 trigger
。最重要的是,我们添加了一个名为 events
的额外 属性,最初是一个空对象。
您可以在 jsfiddle 中查看所有这些的原始代码,我将在这里只介绍代码的结构和逻辑。
events
将保存与每个事件关联的所有处理程序(函数)。第一次添加事件时,我们在events
对象中添加一个eventName
属性,这个属性的值最初是一个空数组。
on
会在events
中找到(或创建)链接到eventName
的数组,并将函数压入数组(注意我们此时不调用函数,我们只是将函数的引用存储在数组中)。
off
将迭代 eventName
的数组,如果找到相同的函数(注意 ===
),则将其从数组中移除。
trigger
将迭代 eventName
的数组并调用每个函数。注意调用函数时调用函数中的this
关键字设置为对象,参数与调用trigger
函数相同(除了第一个参数eventName,被过滤掉) .是的,这意味着您可以向 trigger() 传递任意数量的参数,它们将全部传递给每个处理程序。
我不会详细说明 splice
、slice
、===
、arguments
和 apply
等东西的具体作用,我是确保您可以在全球互联网的其他地方找到更多更好的信息。
您可以为此做很多事情,比如通过一些不错的作用域使用使 events
对象不可见,但这不是问题的一部分,所以我没有理会那个。
如果您看完本文后还有其他问题,请随时提问。我也没有对其进行广泛测试,所以如果您发现任何错误,请告诉我。
编辑:起初我没有通读评论,但现在我还添加了对“*”通配符的支持。基本上,这些函数现在检查通配符,并在删除或触发时迭代 event
对象上的所有 eventName
。您还可以通过不提供函数或提供相同的通配符但使用事件名称来删除事件的所有函数。
EDIT2:在老师的代码中有一些错误 运行,意识到我在迭代时忘记检查 hasOwnProperty
。向上看,这在使用原型时非常重要!
我现在将老师的代码放入我的 jsfiddle 中,向您展示它的工作原理:)
EDIT3 - 关于 'undefined' 日志。
老师的代码调用了 .trigger
5 次,你应该看到 4 个控制台日志,据我所知,它们都是正确的。让我 运行 通过每个触发器,以及后续的控制台日志。
- 您将处理程序添加到
myEvent
,它记录第一个参数
- 你触发
myEvent
,带参数 => 参数(对象)是
记录。
- 您向
yourEvent
添加了一个处理程序,它记录了一个硬编码的
字符串.
- 您触发了
yourEvent
,没有参数 => 记录了硬编码字符串'
- 你触发
*
没有参数 ,所有处理程序 运行 => 未定义被记录,因为没有给出参数,data
在 myEvent
的处理程序中未定义。硬编码字符串也被记录
- 您删除
myEvent
处理程序,触发 myEvent
并确认未调用任何函数
- 您删除所有事件处理程序,触发
*
并确认没有从任何事件调用函数。
老实说,我不知道您希望在第 5 步发生什么,因为您没有提供任何参数,data
被分配 undefined
,这是预期的行为。
如果您想合并第 2 步中给出的数据以使其保留在对象上,请在您的处理程序中进行指示。 (例如,迭代 data
的所有属性并将它们添加到 this
,然后记录 this
)。现在您只需将数据传递给它,它就会被记录下来,然后被丢弃。您还可以在步骤 5 中添加一个参数,然后所有处理程序都会收到它(包括 yourEvent
处理程序,但该处理程序不会分配或使用它)。
说明:
- 无需以任何方式修改代码段即可使此代码正常工作。
- 仅使用普通的旧 JavaScript,不使用第三方库。
- 编写新代码,使下面的代码能够正常工作。
提示:请随意扩展本机对象...尽管这通常是一种不好的做法。
// 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("*")
时无法获得 "arguments";实现 "*"
时无法读取参数对象/参数,因此抛出 undefined
.
document.getElementById("myBtn").addEventListener("click", displayDate);
免责声明 我显然不知道你上的是什么学校什么的,但请不要试图愚弄你的老师来愚弄自己。通过几个简单的问题,他们就会知道您是否理解 material,如果您给出了一个很好的答案但没有支持它的知识,他们就会知道发生了什么。我不是指责你,只是去年毕业后与老师有良好关系的人的友好建议;)
那么,我们该怎么做呢?基本上,您必须向 object
的原型添加一些功能,至少如果您希望这会影响之后制作的 所有 对象。如果您只希望 class 具有此功能,您始终可以创建自己的 class 并将函数添加到该原型。
我们需要在原型中添加 3 个函数,当然是 on
、off
和 trigger
。最重要的是,我们添加了一个名为 events
的额外 属性,最初是一个空对象。
您可以在 jsfiddle 中查看所有这些的原始代码,我将在这里只介绍代码的结构和逻辑。
events
将保存与每个事件关联的所有处理程序(函数)。第一次添加事件时,我们在events
对象中添加一个eventName
属性,这个属性的值最初是一个空数组。
on
会在events
中找到(或创建)链接到eventName
的数组,并将函数压入数组(注意我们此时不调用函数,我们只是将函数的引用存储在数组中)。
off
将迭代 eventName
的数组,如果找到相同的函数(注意 ===
),则将其从数组中移除。
trigger
将迭代 eventName
的数组并调用每个函数。注意调用函数时调用函数中的this
关键字设置为对象,参数与调用trigger
函数相同(除了第一个参数eventName,被过滤掉) .是的,这意味着您可以向 trigger() 传递任意数量的参数,它们将全部传递给每个处理程序。
我不会详细说明 splice
、slice
、===
、arguments
和 apply
等东西的具体作用,我是确保您可以在全球互联网的其他地方找到更多更好的信息。
您可以为此做很多事情,比如通过一些不错的作用域使用使 events
对象不可见,但这不是问题的一部分,所以我没有理会那个。
如果您看完本文后还有其他问题,请随时提问。我也没有对其进行广泛测试,所以如果您发现任何错误,请告诉我。
编辑:起初我没有通读评论,但现在我还添加了对“*”通配符的支持。基本上,这些函数现在检查通配符,并在删除或触发时迭代 event
对象上的所有 eventName
。您还可以通过不提供函数或提供相同的通配符但使用事件名称来删除事件的所有函数。
EDIT2:在老师的代码中有一些错误 运行,意识到我在迭代时忘记检查 hasOwnProperty
。向上看,这在使用原型时非常重要!
我现在将老师的代码放入我的 jsfiddle 中,向您展示它的工作原理:)
EDIT3 - 关于 'undefined' 日志。
老师的代码调用了 .trigger
5 次,你应该看到 4 个控制台日志,据我所知,它们都是正确的。让我 运行 通过每个触发器,以及后续的控制台日志。
- 您将处理程序添加到
myEvent
,它记录第一个参数 - 你触发
myEvent
,带参数 => 参数(对象)是 记录。 - 您向
yourEvent
添加了一个处理程序,它记录了一个硬编码的 字符串. - 您触发了
yourEvent
,没有参数 => 记录了硬编码字符串' - 你触发
*
没有参数 ,所有处理程序 运行 => 未定义被记录,因为没有给出参数,data
在myEvent
的处理程序中未定义。硬编码字符串也被记录 - 您删除
myEvent
处理程序,触发myEvent
并确认未调用任何函数 - 您删除所有事件处理程序,触发
*
并确认没有从任何事件调用函数。
老实说,我不知道您希望在第 5 步发生什么,因为您没有提供任何参数,data
被分配 undefined
,这是预期的行为。
如果您想合并第 2 步中给出的数据以使其保留在对象上,请在您的处理程序中进行指示。 (例如,迭代 data
的所有属性并将它们添加到 this
,然后记录 this
)。现在您只需将数据传递给它,它就会被记录下来,然后被丢弃。您还可以在步骤 5 中添加一个参数,然后所有处理程序都会收到它(包括 yourEvent
处理程序,但该处理程序不会分配或使用它)。