创建 JavaScript 自定义事件

我想用 JavaScript 创建一个自定义事件。

我有一个 WPF 应用程序,其中包含一个 WebBrowser,以及一个包含 JavaScript 的 HTML 页面。

我使用的是打印机。当打印机的状态发生变化时,它会在.NET 中触发一个事件。

然后,使用 WebBrowser 控件的 InvokeScript函数调用 JavaScript 方法 OnPrinterStateChanged(state)

问题是我必须在我的网页中实现方法 OnPrinterStateChanged(state)。我不能更改方法的名称或订阅/取消订阅事件..。

我想将 JavaScript 方法 OnPrinterStateChanged(state)移动到一个单独的 JavaScript 文件中。

我想要的:

  • 在 HTML 页面中订阅/取消订阅事件,并决定在触发事件时要做什么(例如。校对: “ function ChangeState”)
  • 当。NET 事件被触发时,它会调用我分离的 OnPrinterStateChanged(state)。Js 文件,然后触发 JavaScript 事件并调用函数 ChangeState

我找到了一些解决办法,但是我没有成功... ... 最简单的方法是什么?

83097 次浏览

也许像这样?

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);
});

我找到解决办法了。

我不得不把浏览器的 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
});

我喜欢使用这个 EventDispatcher构造函数方法,它使用一个虚拟元素隔离事件,这样它们就不会触发到任何现有的 DOM 元素,也不会触发到 windowdocument

我使用的是 CustomEvent而不是 createEvent,因为它是最新的 接近 你可在此浏览更多资料

我喜欢用以下名称包装每个本机方法:

onofftrigger

function eventDispatcher(){
// Create a dummy DOM element, which is a local variable
var dummy = document.createTextNode('')


// Create custom wrappers with nicer names
return {
off(...args){
dummy.removeEventListener(...args)
return this
},
on(...args){
dummy.addEventListener(...args)
return this
},
trigger(eventName, data){
if( !eventName ) return
      

// if the event should be allowed to bubble,
// then "dummy" must be in the DOM
var e = new CustomEvent(eventName, {detail:data})
dummy.dispatchEvent(e)
return this
}
}
}


////////////////////////////////////
// initialize the event dispatcher by creating an instance in an isolated way
var myEventDispatcher = eventDispatcher();


////////////////////////////////////
// listen to a "foo" event
myEventDispatcher
.on('foo', e => console.log(e.type, e.detail) )
.on('bar', e => console.log(e.type, e.detail) )


////////////////////////////////////
// trigger a "foo" event with some data
myEventDispatcher
.trigger('foo', 123)
.trigger('bar', 987);


上面的 eventDispatcher可以集成到另一个代码中,例如,一个构造函数: (例如某些元件)

function eventDispatcher(){
var dummy = document.createTextNode('')


return {
off(...args){
dummy.removeEventListener(...args)
return this
},
on(...args){
dummy.addEventListener(...args)
return this
},
trigger(eventName, data){
if( !eventName ) return
var e = new CustomEvent(eventName, {detail:data})
dummy.dispatchEvent(e)
return this
}
}
}


/////////////////////////////
// Some component:


var MyComponent = function(){
// merge `EventDispatcher` instance into "this" instance
Object.assign(this, eventDispatcher())
  

// set some default value
this.value = 1
}


MyComponent.prototype = {
set 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("Type:", e.type,", Value:", e.detail) )


// set some value
comp.value = 3;


请参阅我的相关的 < a href = “ https://stackoverflow./a/44432013/104380”> 答案 ,它显示了上面的更复杂的实现

要求: 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();