创建 JavaScript 自定义事件

IT技术 javascript events
2021-03-07 20:26:18

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

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

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

然后,我调用一个OnPrinterStateChanged(state)带有InvokeScriptWebBrowser 控件功能的JavaScript 方法

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

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

我想要的是 :

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

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

4个回答

也许像这样?

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/...替换,但我还有另一个没有详细信息的脚本错误。
2021-04-26 20:26:18
好的,谢谢,告诉你是否知道这些库之一或如何使用 Jquery 做到这一点......否则,无论如何,谢谢你
2021-04-27 20:26:18
它是来自 WPF 的 WebBrowser 所以它是 Internet Explorer
2021-04-29 20:26:18
@Gab 在哪个浏览器中?
2021-05-01 20:26:18
@Gab,这个嵌入式 WebBrowser 当时似乎已经过时,并且可能不支持自定义事件。我建议您使用微型库来支持自定义事件并使用相同的策略。这里有一些microjs.com/#events
2021-05-16 20:26:18

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

我正在使用CustomEvent而不是createEvent因为它是较新的方法。在这里阅读更多

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

on, off,trigger

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可以集成到另一个代码中,例如,一个构造函数:( 例如某个组件)


👉看我的相关回答,里面展示了上面更复杂的实现

不会使用ontrigger创建与 jQuery 的不兼容?
2021-04-24 20:26:18
完美运行,谢谢!
2021-05-03 20:26:18
不,因为这些方法是在EventDispatcherObject上声明的,它不是一个 jQuery 对象......它只会在你扩展任何带有 实例的 jQuery 对象时发生冲突EventDispatcher,没有人会这样做,因为它没有意义。
2021-05-16 20:26:18

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

我不得不将 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
});
请记住,document.createEvent已被CustomEventorEvent构造函数替换,您应该使用它来代替。我很确定 IE 11 支持它们。
2021-04-24 20:26:18
IE11 确实支持CustomEvent@Derick
2021-05-02 20:26:18
Mozilla为不支持的浏览器提供了一个简单的 polyfillCustomEvent(基本上只是 IE)
2021-05-06 20:26:18
IE也不支持。您必须使用“老式方式”来获得 IE 支持。developer.mozilla.org/en-US/docs/Web/Guide/Events/...
2021-05-14 20:26:18

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