我想用JavaScript创建一个自定义事件。
我有一个内部有WebBrowser的WPF应用程序,以及一个带有JavaScript的HTML页面。
我使用打印机。当打印机的状态发生变化时,它会触发.NET中的事件。
然后,我使用WebBrowser控件的OnPrinterStateChanged(state)
函数调用JavaScript方法InvokeScript
。
问题是我必须在我的网页中实现方法OnPrinterStateChanged(state)
。我无法更改方法的名称或订阅/取消订阅活动......
我想将JavaScript方法OnPrinterStateChanged(state)
移到单独的JavaScript文件中。
我想要的是什么:
OnPrinterStateChanged(state)
,然后触发JavaScript事件并调用函数ChangeState
。我找到了一些解决方案,但我没有设法让它工作......最简单的方法是什么?
答案 0 :(得分:83)
也许是这样的?
function OnPrinterStateChanged(state) {
var evt = new CustomEvent('printerstatechanged', { detail: state });
window.dispatchEvent(evt);
}
//Listen to your custom event
window.addEventListener('printerstatechanged', function (e) {
console.log('printer state changed', e.detail);
});
另一种解决方案是使用函数组合,但是很难删除特定的侦听器。
function OnPrinterStateChanged(state) {}
function compose(fn1, fn2) {
return function () {
fn1.apply(this, arguments);
fn2.apply(this, arguments);
};
}
//Add a new listener
OnPrinterStateChanged = compose(OnPrinterStateChanged, function (state) {
console.log('listener 1');
});
//Add another one
OnPrinterStateChanged = compose(OnPrinterStateChanged, function (state) {
console.log('listener 2');
});
编辑:
以下是如何使用jQuery实现的。
function OnPrinterStateChanged(state) {
var evt = $.Event('printerstatechanged');
evt.state = state;
$(window).trigger(evt);
}
//Listen to your custom event
$(window).on('printerstatechanged', function (e) {
console.log('printer state changed', e.state);
});
答案 1 :(得分:6)
我喜欢使用这个EventDispatcher
构造函数方法,它使用虚拟元素隔离事件,以便不会在任何现有DOM元素上触发它们,也不会window
或document
我使用的是
CustomEvent
,而不是createEvent
,因为它是较新的 做法。 Read more here
我喜欢用这些名称包装每个本机方法:
on
,off
,trigger
function EventDispatcher(){
// Create a dummy DOM element
var dummy = document.createTextNode('');
// Create custom wrappers with nicer names
this.off = dummy.removeEventListener.bind(dummy);
this.on = dummy.addEventListener.bind(dummy);
this.trigger = function(eventName, data){
if( !eventName ) return;
var e = new CustomEvent(eventName, {"detail":data});
dummy.dispatchEvent(e);
}
}
////////////////////////////////////
// initialize the event dispatcher by creating an instance in an isolated way
var myEventDispatcher = new EventDispatcher();
////////////////////////////////////
// listen to a "foo" event
myEventDispatcher.on('foo', e =>{
console.log(e.type, e.detail);
});
////////////////////////////////////
// trigger a "foo" event with some data
myEventDispatcher.trigger('foo', 123);

EventDispatcher
可用于其他代码(例如某些组件)
function EventDispatcher(){
// Create a dummy DOM element
var dummy = document.createTextNode('');
// Create custom wrappers with nicer names
this.off = dummy.removeEventListener.bind(dummy);
this.on = dummy.addEventListener.bind(dummy);
this.trigger = function(eventName, data){
if( !eventName ) return;
var e = new CustomEvent(eventName, {"detail":data});
dummy.dispatchEvent(e);
}
}
/////////////////////
// Some component: //
/////////////////////
var MyComponent = function(){
// set some default value
this.value = 1;
// merge `EventDispatcher` instance into "this" ('MyComponent' instance)
Object.assign(this, new EventDispatcher());
}
MyComponent.prototype = {
set : function(v){
this.value = v;
this.trigger('change', v);
}
}
var comp = new MyComponent();
// bind a listener to "comp" (which itself is an instance of "MyComponent")
comp.on('change', e =>{
console.log("event type:", e.type, " | event value:", e.detail);
});
// set some value
comp.set(3);

答案 2 :(得分:1)
好的,我找到了解决方案。
我不得不将WebBrowser IE版本更改为Internet Explorer 11:http://weblog.west-wind.com/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version
然后:
function OnPrinterStateChanged(state) {
var evt = document.createEvent("Event");
evt.state = state;
evt.initEvent("printerstatechanged", true, false);
window.dispatchEvent(evt);
}
window.addEventListener('printerstatechanged', function (e) {
// Do something
});
答案 3 :(得分:1)
要求:ES6
let MyClass = (function () {
let __sym = Symbol('MyClass');
class MyClass {
constructor() {
this[__sym] = {};
}
on(event, callback) {
this[__sym][event] = { callback: callback }
}
getError() {
let event = this[__sym].error;
if (event && event.callback) {
event.callback('some parameter');
}
}
}
return MyClass;
}());
let myClass = new MyClass();
myClass.on('error', function (e) {
console.log('error:', e);
});
console.log('before getting error:');
myClass.getError();