我想要的是一个提供一些事件的自定义对象。 例如:
var CustomObjectTextChangedEventName = 'textChanged';
var CustomObject = function () {
var _this = this;
var _text = "";
_this.OnTextChanged = document.createEvent("Event");
_this.OnTextChanged.initEvent(CustomObjectTextChangedEventName, true, false);
_this.ChangeText = function (newText) {
_text = newText;
fireTextChanged();
};
function fireTextChanged() {
_this.dispatchEvent(_this.OnTextChanged);
}
}
使用该事件的代码如下:
myCustomObject = new CustomObject();
myCustomObject.addEventListener(CustomObjectTextChangedEventName, handleTextChanged, false);
正如您所看到的......在JS中使用事件的默认方式。 但是我不能让它变得烦人......
目前我的问题是我的对象没有实现“addEventListener”和“dispatchEvent”。但是这个函数是从“元素”中正常实现的......
我可以以某种方式使它们可用,还是我必须为自己实现它们? 我该如何实施它们? 我是否必须实施自己的事件处理? (有一个内部处理程序列表,一个“添加” - 和“删除” - 处理程序函数,并在我想要触发事件时触发每个处理程序)
问候!
答案 0 :(得分:17)
addEventListener
函数是Element
类的方法。一种方法是CustomObject
继承Element
,如下所示:
CustomObject.prototype = Element.prototype;
问题是Element
类在不同的浏览器中可能有不同的实现。因此,例如触发事件可能并不容易(参见this post)。
所以我建议你自己这样做。这并不难,尝试这样的事情:
var CustomObject = function () {
var _this = this;
_this.events = {};
_this.addEventListener = function(name, handler) {
if (_this.events.hasOwnProperty(name))
_this.events[name].push(handler);
else
_this.events[name] = [handler];
};
_this.removeEventListener = function(name, handler) {
/* This is a bit tricky, because how would you identify functions?
This simple solution should work if you pass THE SAME handler. */
if (!_this.events.hasOwnProperty(name))
return;
var index = _this.events[name].indexOf(handler);
if (index != -1)
_this.events[name].splice(index, 1);
};
_this.fireEvent = function(name, args) {
if (!_this.events.hasOwnProperty(name))
return;
if (!args || !args.length)
args = [];
var evs = _this.events[name], l = evs.length;
for (var i = 0; i < l; i++) {
evs[i].apply(null, args);
}
};
}
现在使用它就像:
var co = new CustomObject();
co.addEventListener('textChange', function(name) {
console.log(name);
});
co.fireEvent('textChange', ['test']);
这是一个基本的解决方案。你可能想改变它,但我认为你应该掌握这个想法。
答案 1 :(得分:1)
我不确定100%,但接下来是我在这个问题上的旧研究结果:
// code source: MDN: https://developer.mozilla.org/en/DOM/element.removeEventListener
// without changes
if (!Element.prototype.addEventListener) {
var oListeners = {};
function runListeners(oEvent) {
if (!oEvent) { oEvent = window.event; }
for (var iLstId = 0, iElId = 0, oEvtListeners = oListeners[oEvent.type]; iElId < oEvtListeners.aEls.length; iElId++) {
if (oEvtListeners.aEls[iElId] === this) {
for (iLstId; iLstId < oEvtListeners.aEvts[iElId].length; iLstId++) { oEvtListeners.aEvts[iElId][iLstId].call(this, oEvent); }
break;
}
}
}
Element.prototype.addEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) {
if (oListeners.hasOwnProperty(sEventType)) {
var oEvtListeners = oListeners[sEventType];
for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) {
if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; }
}
if (nElIdx === -1) {
oEvtListeners.aEls.push(this);
oEvtListeners.aEvts.push([fListener]);
this["on" + sEventType] = runListeners;
} else {
var aElListeners = oEvtListeners.aEvts[nElIdx];
if (this["on" + sEventType] !== runListeners) {
aElListeners.splice(0);
this["on" + sEventType] = runListeners;
}
for (var iLstId = 0; iLstId < aElListeners.length; iLstId++) {
if (aElListeners[iLstId] === fListener) { return; }
}
aElListeners.push(fListener);
}
} else {
oListeners[sEventType] = { aEls: [this], aEvts: [ [fListener] ] };
this["on" + sEventType] = runListeners;
}
};
Element.prototype.removeEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) {
if (!oListeners.hasOwnProperty(sEventType)) { return; }
var oEvtListeners = oListeners[sEventType];
for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) {
if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; }
}
if (nElIdx === -1) { return; }
for (var iLstId = 0, aElListeners = oEvtListeners.aEvts[nElIdx]; iLstId < aElListeners.length; iLstId++) {
if (aElListeners[iLstId] === fListener) { aElListeners.splice(iLstId, 1); }
}
};
}
Element.prototype
替换为CustomObject.prototype
。要支持dispathEvent
,您必须添加CustomObject.prototype.dispatchEvent = runListener;
代码行。也可以更好地将此代码封装到闭包函数中; 我没有在我的应用中测试过这个,但也许这可以帮到你。
<强>更新强>
下一个链接指向包含XObject()
类的代码源,该类支持事件添加/删除和调度事件。包括测试示例。所有代码都基于上面的答案。
http://jsfiddle.net/8jZrR/
答案 2 :(得分:1)
我用奇怪的代码改进了我的样本。我仍然会将事件处理部分提取到“基类”......也许当有更多的时间=)
还有一个使用jQuery的示例!
<!doctype html>
<html lang="en">
<head>
<title>Custom Events Test</title>
<meta charset="utf-8">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script>
/* jQuery
var CustomObjectTextChangedEventName = 'textChanged';
var CustomObject = function () {
var _this = this;
var _text = "";
_this.ChangeText = function (newText) {
_text = newText;
fireTextChanged();
};
function fireTextChanged() {
$(_this).trigger(CustomObjectTextChangedEventName, _text);
}
}
var myCustomObject;
$(document).ready(function () {
myCustomObject = new CustomObject();
$(myCustomObject).bind(CustomObjectTextChangedEventName, handleTextChanged);
})
function handleTextChanged(event, msg) {
window.alert(msg);
}
function buttonClick() {
var newText = document.getElementById('tbText').value;
myCustomObject.ChangeText(newText);
}
*/
var CustomObjectTextChangedEventName = 'textChanged';
var CustomObject = function (alias) {
var _this = this;
var _events = {};
var _text = "";
_this.Alias = alias;
_this.OnTextChanged = document.createEvent("Event");
_this.OnTextChanged.initEvent(CustomObjectTextChangedEventName, true, false);
_this.ChangeText = function (newText) {
var args = new TextChangedEventArgs();
args.OldText = _text;
args.NewText = newText;
_text = newText;
fireEvent(CustomObjectTextChangedEventName, args);
};
_this.addEventListener = function (name, handler) {
if (_events.hasOwnProperty(name))
_events[name].push(handler);
else
_events[name] = [handler];
};
_this.removeEventListener = function (name, handler) {
/* This is a bit tricky, because how would you identify functions?
This simple solution should work if you pass THE SAME handler. */
if (!_events.hasOwnProperty(name))
return;
var index = _events[name].indexOf(handler);
if (index != -1)
_events[name].splice(index, 1);
};
function fireEvent(name, args) {
if (!_events.hasOwnProperty(name))
return;
var evs = _events[name], l = evs.length;
for (var i = 0; i < l; i++) {
evs[i](_this, args);
}
}
}
var TextChangedEventArgs = function () {
var _this = this;
_this.OldText = null;
_this.NewText = null;
}
var myCustomObject;
var myCustomObject2;
window.onload = function () {
myCustomObject = new CustomObject("myCustomObject");
myCustomObject.addEventListener(CustomObjectTextChangedEventName, handleTextChanged);
myCustomObject2 = new CustomObject("myCustomObject2");
myCustomObject2.addEventListener(CustomObjectTextChangedEventName, handleTextChanged);
};
function handleTextChanged(sender, args) {
window.alert('At ' + sender.Alias + ' from [' + args.OldText + '] to [' + args.NewText + ']');
}
function buttonClick() {
var newText = document.getElementById('tbText').value;
myCustomObject.ChangeText(newText);
}
function buttonClick2() {
var newText = document.getElementById('tbText2').value;
myCustomObject2.ChangeText(newText);
}
</script>
</head>
<body>
<input type="text" id="tbText" />
<input type="button" value="Change" onclick="buttonClick();" />
<input type="text" id="tbText2" />
<input type="button" value="Change" onclick="buttonClick2();" />
</body>
答案 3 :(得分:0)
用法:jsfiddle
这是一种天真的方法,但可能适用于某些应用程序:
CustomEventTarget.prototype = {
'constructor': CustomEventTarget,
on: function( ev, el ) { this.eventTarget.addEventListener( ev, el ) },
off: function( ev, el ) { this.eventTarget.removeEventListener( ev, el ) },
emit: function( ev ) { this.eventTarget.dispatchEvent( ev ) }
}
function CustomEventTarget() { this.eventTarget = new EventTarget }