创建JavaScript自定义事件


69

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

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

我使用打印机。打印机状态更改时,它将触发.NET中的事件。

然后,我OnPrinterStateChanged(state)使用InvokeScriptWebBrowser控件的功能调用JavaScript方法。

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

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

我想要的是 :

  • 在我的HTML页面中订阅/取消订阅该事件,并确定触发事件时我想做什么(例如:“功能ChangeState”)
  • 触发.NET事件时,它将调用OnPrinterStateChanged(state)我单独的.js文件的,然后触发JavaScript事件并ChangeState调用该函数。

我找到了一些解决方案,但是我没有设法使它起作用。最简单的方法是什么?


您找到了什么解决方案?请显示您迄今为止的尝试
musefan 2014年

我在nczonline.net/blog/2010/03/09/custom-events-in-javascript中找到了,但是就像我说的,我是一个初学者,我不知道它是否可以满足我的要求,以及在哪里使用此代码...
Gab 2014年

Answers:


107

也许像这样?

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

谢谢您的回答!但是我遇到了这个错误:“对象不支持属性或方法'addEventListener'”任何想法为什么?我尝试用“ AttachEvent”(stackoverflow.com/questions/12216301/…)替换,但是我还有另一个脚本错误,没有详细信息。
2014年

@Gab在哪个浏览器中?
plalx 2014年

这是WPF的WebBrowser,因此它是Internet Explorer
Gab 2014年

@Gab,那么这个嵌入式WebBrowser似乎已过时,并且可能不支持自定义事件。我建议您将微库用于自定义事件支持,然后使用相同的策略。这是一些microjs.com/#events
plalx 2014年

好的,谢谢,告诉您是否知道这些库之一,或者例如如何使用Jquery进行处理...否则,还是要谢谢您
Gab 2014年

13

我喜欢使用此EventDispatcher构造函数方法,该方法使用伪元素隔离事件,因此不会在任何现有DOM元素上触发事件,也不会在windowor上触发它们document

我使用的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代码可以集成到另一个代码中,例如,一个Constructor :( 例如,某些组件)


查看有关问题的相关答案“ Vanilla JavaScript中的事件处理程序命名空间”


1
不会使用jQueryon并与它trigger产生不兼容性吗?
马克·克雷默

1
不,因为这些方法是在EventDispatcher对象(不是jQuery对象)上声明的。.仅当使用实例扩展任何jQuery对象时,它才会发生冲突EventDispatcher,因为没有意义,没有人会这样做。
vsync

完美运行,谢谢!
Mkey

2

好的,我找到了解决方案。

我必须将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
});

4
请记住,document.createEvent它已被CustomEventEvent构造函数取代,而应改用它。我很确定IE 11支持它们。
plalx

2
IE不支持。您必须使用“老式方式”来获得IE支持。developer.mozilla.org/en-US/docs/Web/Guide/Events/…–
Derick

2
IE11支持 CustomEvent@Derick
VSYNC

Mozilla有一个简单的polyfill为不支持的浏览器CustomEvent(基本上只是IE)
Kyle Fox,

2

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.