创建JavaScript自定义事件

时间:2014-04-28 15:07:09

标签: javascript events

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

我有一个内部有WebBrowser的WPF应用程序,以及一个带有JavaScript的HTML页面。

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

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

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

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

我想要的是什么:

  • 订阅/取消订阅我的HTML页面中的活动,并决定触发事件时我想做什么(例如:“function ChangeState”)
  • 当触发.NET事件时,它会调用我单独的.js文件的OnPrinterStateChanged(state),然后触发JavaScript事件并调用函数ChangeState

我找到了一些解决方案,但我没有设法让它工作......最简单的方法是什么?

4 个答案:

答案 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元素上触发它们,也不会windowdocument

  

我使用的是CustomEvent,而不是createEvent,因为它是较新的   做法。 Read more here

我喜欢用这些名称包装每个本机方法:

onofftrigger



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