指示应在 dojo 子类中触发事件的最佳方式

Best way to indicate an event should be fired in a dojo subclass

我正在使用 dojo 在 javascript 中设计一个抽象的 superclass。 class 的目的是为任何 UI 元素定义契约,使用户能够 select 具有唯一标识符的实体。到目前为止,这是我的代码。

define(
[   
    "dojo/Evented",
    "dojo/_base/declare"
],
function(Evented, declare){
    var NotImplementedException = "Method not implemented"; 
    return declare("EntitySelector", Evented, {
        //it's implementation should change the entity selected by the UI
        select: function(id){
            throw NotImplementedException;
        },
        //it's implemantation should populate the UI with the data to be selected.
        setData: function(dataStore){
            throw NotImplementedException;
        }

    });
});

我还需要 subclasses 触发一个 onSelect 事件,这样我就可以响应用户实际 selecting 一个实体。

有没有办法(文档除外)指示子classes 应该在其实现时触发 onSelect 事件?

例如,在 Java 中,您通常会定义一个 public void addEventListener(ListenerInterface) 方法来指示子classes 应该触发一个事件。在 C# 中,您可以声明一个 event EventHandler 来实现类似的效果。

在 dojo 或通用 Java 脚本中有没有办法实现这个?

您可以使用类似下面的代码。
它依赖于 _WidgetBase 提供的 widget 生命周期,并检查是否实现了某些方法。
此外,它会在触发 "select" 方法时自动添加 "onSelect" 事件。
另一种方法是挂钩 on 方法并检查是否附加了事件(查看 foo 事件的情况。

require([
  "dojo/Evented",
  "dojo/aspect",  
  "dijit/_WidgetBase",
  "dojo/_base/lang",
  "dojo/_base/declare"
], function(Evented, aspect, _WidgetBase, lang, declare) {
  var NotImplementedException = "Method not implemented";

  var EntitySelector = declare([_WidgetBase, Evented], {
    hasOnFooEvent: false,
    
    postMixInProperties: function() {

      if (typeof this.select !== 'function') {
        throw NotImplementedException;
      } else {
        this.own(aspect.after(this, 'select', lang.hitch(this, 'emit', 'onSelect')))
      }
      if (typeof this.setData !== 'function') {
        throw NotImplementedException;
      }
      this.inherited(arguments);
    },
    
    on: function(eventName) {
      if(eventName === 'foo') {
        this.hasOnFooEvent = true;
      }
      this.inherited(arguments);
    },
    postCreate: function() {
      if(!this.hasOnFooEvent) {
         throw NotImplementedException;
      }
      this.inherited(arguments);
    }
  });

  var NotOkWidget = declare(EntitySelector, {});

  var OkWidget = declare(EntitySelector, {
    postCreate: function() {
      this.on('foo', function() {});
      this.inherited(arguments);
    },
    select: function() {},
    setData: function() {}
  });
  
  
  try {
    var a = new NotOkWidget();
  } catch (e) {
    console.log('Implementation error on NotOkWidget');
  }
  try {
    var a = new OkWidget();
    a.on('onSelect', function() { console.log('onSelect event is fired'); });
    a.select();
  } catch (e) {
    console.log('Implementation error on OkWidget');
  }

});
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>