Hug*_*ing 56 javascript object addeventlistener cordova
我创建了一个有几种方法的对象.其中一些方法是异步的,因此我想使用事件来在方法完成时执行操作.为此,我尝试将addEventListener添加到对象.
var iSubmit = {
addEventListener: document.addEventListener || document.attachEvent,
dispatchEvent: document.dispatchEvent,
fireEvent: document.fireEvent,
//the method below is added for completeness, but is not causing the problem.
test: function(memo) {
var name = "test";
var event;
if (document.createEvent) {
event = document.createEvent("HTMLEvents");
event.initEvent(name, true, true);
} else {
event = document.createEventObject();
event.eventType = name;
}
event.eventName = name;
event.memo = memo || { };
if (document.createEvent) {
try {
document.dispatchEvent(event);
} catch (ex) {
iAlert.debug(ex, 'iPushError');
}
} else {
document.fireEvent("on" + event.eventType, event);
}
}
}
iSubmit.addEventListener("test", function(e) { console.log(e); }, false);
//This call is added to have a complete test. The errors are already triggered with the line before this one.
iSubmit.test();
Run Code Online (Sandbox Code Playgroud)
这将返回错误: Failed to add eventlisterens: TypeError: 'addEventListener' called on an object that does not implement interface EventTarget."
现在这个代码将用于一个phonegap应用程序,当我这样做时,它正在使用android/ios.然而,在测试期间,如果我能够在至少一个浏览器中使用它将会很好.
PS>我知道我可以启用冒泡然后监听文档根目录,但我希望只有一点点OOP,每个对象可以独立工作.
Eva*_*You 48
addEventListener
适用于实现某些与事件相关的接口的DOM元素.如果您想在纯JavaScript对象上使用事件系统,那么您正在寻找自定义事件系统.一个例子是Backbone.Events
Backbone.js.基本思想是使用对象作为哈希来跟踪已注册的回调.
我个人使用这个:https://github.com/component/emitter
这是一个相当简单和优雅的解决方案-带有般甜美短方法名on()
,off()
和emit()
.您可以使用new Emitter()
或使用Emitter(obj)
将事件功能混合到现有对象中来创建新实例.请注意,此库是为与CommonJS模块系统一起使用而编写的,但您可以通过删除该module.exports = ...
行在其他任何位置使用它.
Pin*_*nal 15
如果你想听一个javascript对象,你有三种方法:
Object get/set operators
,Object.defineProperty
,Object.prototype.watch
或者Proxy API
Object.observe
.Works Chrome 25+(2014年1月).但在2016年被弃用了关于sup/pub模式:
您需要发布事件.
关于本机实现:
Object get/set operators
足以听取添加,删除,更改,获取事件.运营商有很好的支持.仅在IE8中存在问题.但是如果你想在IE8中使用get/set Object.defineProperty
但是在DOM对象上使用或者使用Object.defineProperty sham.Object.prototype.watch
有良好的ES5 polyfill.Proxy API
需要ES Harmony支持.Object.observe示例
var o = {};
Object.observe(o, function (changes) {
changes.forEach(function (change) {
// change.object contains changed object version
console.log('property:', change.name, 'type:', change.type);
});
});
o.x = 1 // property: x type: add
o.x = 2 // property: x type: update
delete o.x // property: x type: delete
Run Code Online (Sandbox Code Playgroud)
Rav*_*ine 15
如果您不需要真正的事件功能(例如冒泡,stopPropagation),那么您可以实现自己的事件.addEventListener只是DOM的一个API,因此您不需要为DOM之外的对象提供它.如果你想在一个对象周围创建一个偶数模式,这是一个很好的方法,它不需要任何额外的浏览器API,并且应该是非常向后兼容的.
假设您有一个对象,您希望在调用dispatch方法时触发一系列事件:
var OurDispatcher, dispatcher;
OurDispatcher = (function() {
function OurDispatcher() {
this.dispatchHandlers = [];
}
OurDispatcher.prototype.on = function(eventName, handler) {
switch (eventName) {
case "dispatch":
return this.dispatchHandlers.push(handler);
case "somethingElse":
return alert('write something for this event :)');
}
};
OurDispatcher.prototype.dispatch = function() {
var handler, i, len, ref;
ref = this.dispatchHandlers;
for (i = 0, len = ref.length; i < len; i++) {
handler = ref[i];
setTimeout(handler, 0);
}
};
return OurDispatcher;
})();
dispatcher = new OurDispatcher();
dispatcher.on("dispatch", function() {
return document.body.innerHTML += "DISPATCHED</br>";
});
dispatcher.on("dispatch", function() {
return document.body.innerHTML += "DISPATCHED AGAIN</br>";
});
dispatcher.dispatch();
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,它确实不必比那更复杂.通过这种方式,您可以对事件进行一些不错的控制,而不必担心向后兼容性或外部库,因为所有内容都得到了广泛支持.从技术上讲,你甚至可以不使用setTimeout并在没有任何API的情况下处理你的回调.任何其他像stopPropagation()都必须自己处理.
https://jsfiddle.net/ozsywxer/
当然,还有用于CustomEvent的polyfill,但除非我需要高级事件功能,否则我更喜欢将自己的事件系统包装到"类"中并使用它扩展其他类/函数.
这是CoffeeScript版本,它是JavaScript的衍生版本:https: //jsfiddle.net/vmkkbbxq/1/
^^有点容易理解.
tif*_*fon 10
有两个问题.
首先,该iSubmit.addEventListener()
方法实际上是EventTarget
DOM接口上的一个方法:
这些仅用于DOM元素.通过将它iSubmit
作为方法添加到对象中,您可以在不是的对象上调用它EventTarget
.这就是Chrome抛出Uncaught TypeError: Illegal invocation
JavaScript错误的原因.
第一个问题是至关重要的,但是如果您可以使用EventTarget#addEventListener()
您的代码将无法工作,因为事件正在添加到iSubmit
但是已分派document
.一般情况下,同一对象的方法需要安装事件侦听器,并分派事件(除非你使用冒泡事件,这是时要使用不同的故事 -注:冒泡并不限于JavaScript或DOM相关的事件,例如).
在自己的对象中使用自定义事件是很正常的.正如Evan Yu所说,有这样的图书馆.这是一对夫妇:
我已经习惯了js-signals
并且非常喜欢它.我从未使用过Wolfy87/EventEmitter
,但它看起来很漂亮.
如果您使用,您的示例可能类似于以下内容 js-signals
var iSubmit = {
finished: new signals.Signal(),
test: function test(memo) {
this.finished.dispatch(memo || {});
}
};
iSubmit.finished.add(function(data) {
console.log('finished:', data);
});
iSubmit.test('this is the finished data');
// alternatively
iSubmit.finished.dispatch('this is dispatched directly from the signal');
Run Code Online (Sandbox Code Playgroud)
小智 8
这是一个简单的事件发射器:
class EventEmitter {
on(name, callback) {
var callbacks = this[name];
if (!callbacks) this[name] = [callback];
else callbacks.push(callback);
}
dispatch(name, event) {
var callbacks = this[name];
if (callbacks) callbacks.forEach(callback => callback(event));
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var emitter = new EventEmitter();
emitter.on('test', event => {
console.log(event);
});
emitter.dispatch('test', 'hello world');
Run Code Online (Sandbox Code Playgroud)
如果您在 Node.js 环境中,那么您可以使用Node 的 EventEmitter 类:
自定义对象.js
const EventEmitter = require('events');
class CustomObject extends EventEmitter {
constructor() {
super();
}
doSomething() {
const event = {message: 'Hello World!'};
this.emit('myEventName', event);
}
}
module.exports = CustomObject;
Run Code Online (Sandbox Code Playgroud)
用法:
const CustomObject = require('./CustomObject');
// 1. Create a new instance
const myObject = new CustomObject();
// 2. Subscribe to events with ID "myEventName"
myObject.on('myEventName', function(event) {
console.log('Received event', event);
});
// 3. Trigger the event emitter
myObject.doSomething();
Run Code Online (Sandbox Code Playgroud)
如果您想在 Node.js 环境之外使用 Node 的 EventEmitter,那么您可以使用webpack(最好是 v2.2 或更高版本)将您的捆绑包CustomClass
与 EventEmitter polyfill(由 webpack 构建)一起使用。
这是它的工作原理(假设您使用 全局安装了 webpack npm install -g webpack
):
webpack CustomObject.js bundle.js --output-library=CustomObject
bundle.js
在您的 HTML 页面中(它将公开window.CustomObject
)索引.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Title</title>
<script src="bundle.js"></script>
</head>
<body>
<script>
// 1. Create a new instance
const myObject = new window.CustomObject();
// 2. Subscribe to events with ID "myEventName"
myObject.on('myEventName', function(event) {
console.log('Received event', event);
});
// 3. Trigger the event emitter
myObject.doSomething();
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
小智 5
只是猜测;我自己还没有尝试过。但是您可以创建一个虚拟元素,并触发/侦听该虚拟元素上的事件。另外,我更喜欢不使用库。
function myObject(){
//create "dummy" element
var dummy = document.createElement('dummy');
//method for listening for events
this.on = function(event, func){dummy.addEventListener(event, func);};
//you need a way to fire events
this.fireEvent = function(event, obj){
dummy.dispatchEvent(new CustomEvent(event, {detail: obj}));
}
}
//now you can use the methods in the object constructor
var obj = new myObject();
obj.on("custom", function(e){console.log(e.detail.result)});
obj.fireEvent("custom", {result: "hello world!!!"});
Run Code Online (Sandbox Code Playgroud)
我已经能够通过将元素包装在 javascript 类中来实现此目的。重要的一点是元素不必存在于 dom 中。此外,元素标签名称可以是任何内容,例如自定义类名称。
'''
class MyClass
{
constructor(options )
{
this.el = document.createElement("MyClass");//dummy element to manage events.
this.el.obj= this; //So that it is accessible via event.target.obj
}
addEventListener()
{
this.el.addEventListener(arguments[0],arguments[1]);
}
raiseEvent()
{
//call this function or write code below when the event needs to be raised.
var event = new Event('dataFound');
event.data = messageData;
this.el.dispatchEvent(event);
}
}
let obj = new MyClass();
obj.addEventListener('dataFound',onDataFound);
function onDataFound()
{
console.log('onDataFound Handler called');
}
Run Code Online (Sandbox Code Playgroud)
'''
归档时间: |
|
查看次数: |
65763 次 |
最近记录: |