如何从另一个框架向 Ember 触发事件

Posted

技术标签:

【中文标题】如何从另一个框架向 Ember 触发事件【英文标题】:How to fire an event to Ember from another framework 【发布时间】:2013-01-05 16:01:12 【问题描述】:

我们使用的是 ember 的 pre4 版本。

我们有一个与 ember 并行工作的框架 (SignalR),它处理对我们应用程序的实时通知。在旧版本的 ember 中,我们能够访问路由器/控制器的全局引用。但是对于新版本的 Ember,这不再是可能的了。 (这可以) 我们尝试了不同的方法,例如在顶部路由中设置全局控制器:

setupController: function()
    app.appController = this.controllerFor('app');

并向这个控制器发送一个事件,它会像这样冒泡到路由:

notificator.update = function (context)  
    app.appController.send('notificationOccured', context);
);

但这感觉就像是在与刚刚删除全局引用的 Ember 团队合作。

那么现在来回答一个大问题:有没有更好的方法可以从 Ember 外部访问路由器或控制器?最好使用上下文向其中任何一个发送事件。

感谢所有帮助!

【问题讨论】:

【参考方案1】:

那么现在来回答一个大问题:有没有更好的方法可以从 Ember 外部访问路由器或控制器?最好使用上下文向其中任何一个发送事件。

是的。这听起来很适合 ember 仪表模块。让适当的控制器订阅 SignalR 事件,然后在您的应用处理实时通知时触发它们。

首先,向 ApplicationController 添加一个方法来处理更新。如果未在此处定义,则事件将冒泡到路由器。

App.ApplicationController = Ember.Controller.extend(
  count: 0,
  name: 'default',
  signalrNotificationOccured: function(context) 
    this.incrementProperty('count');
    this.set('name', context.name);
  
);

接下来,通过订阅 signalr.notificationOccured 事件来设置您的 ApplicationController。使用 before 回调记录事件并将其有效负载发送到控制器。

App.ApplicationRoute = Ember.Route.extend(
  setupController: function (controller, model) 
    Ember.Instrumentation.subscribe("signalr.notificationOccured", 
      before: function(name, timestamp, payload) 
        console.log('Recieved ', name, ' at ' + timestamp + ' with payload: ', payload);
        controller.send('signalrNotificationOccured', payload);
      ,
      after: function() 
    );
  
);

然后从您的 SignalR 应用程序中,使用 Ember.Instrumentation.instrument 将有效负载发送到您的 ApplicationController,如下所示:

notificator.update = function (context)  
  Ember.Instrumentation.instrument("signalr.notificationOccured", context);
);

我在此处发布了带有模拟 SignalR 通知的工作副本:http://jsbin.com/iyexuf/1/edit

有关检测模块的文档可以在 here 找到,也可以查看 specs 了解更多示例。

【讨论】:

instrument 作为发送信号的名称在我看来相当混乱。 '使用Ember.instrument 检测代码块的确切含义是什么:发送具有指定名称和有效负载的信号并在最后调用回调?顺便说一句,很好。 甜,这太完美了!这个设计正是我想要的。也可以像魅力一样工作。 Mike,这可能正是我想要的,但这可以用于通用事件还是仅用于渲染?它只是向上冒泡还是任何对象都可以侦听由任何其他对象触发的事件?理想情况下,我希望能够复制 jQuery 的 $.trigger(),它可以让您在任何地方设置定制事件,并从任何地方触发它们。 它可用于通用事件,不确定您所说的向上冒泡是什么意思,但检测并不特定于渲染。确保任何对象都可以监听由任何其他对象触发的事件。 我喜欢这种方法,但如果你想在更瞬态的控制器(即不是 ApplicationController)中使用它,它需要做更多的工作。在这种情况下,我们还需要注意取消订阅,否则我们会将事件传递给已经销毁的控制器。在我们的应用程序中,我们最终订阅了activate 钩子并取消订阅了deactivate 钩子。【参考方案2】:

您可能不应该这样做,但这里有一种方法可以访问应用程序的控制器、视图、模型和路由器实例。当你的应用初始化时,控制器、视图、模型和路由器都注册在应用容器__container__

APP.__container__.lookup('controller:foo').get('content');
APP.__container__.lookup('view:foo').get('templateName');
APP.__container__.lookup('router:main');

我认为你应该做的是在 Ember 中封装对 3rd 方库的调用,让 Ember 管理整个应用程序。请参阅this attempt 以使 JQuery UI 具有 ember-aware 感知能力

【讨论】:

是的,我们考虑过使用 container,但我认为是 @wycats 将其从容器重命名为 container,以便开发人员应该'真的' 明白不要使用它 :) 所以从现在开始我将远离 container。但我会看看 lukes JQuery-UI-Ember 的尝试。谢谢你的链接! 这适用于我的目的,谢谢。有没有其他方法可以避免使用容器?

以上是关于如何从另一个框架向 Ember 触发事件的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个函数触发选择事件 [SAPUI5]

向zepto.js学习如何手动(trigger)触发DOM事件

jQuery:从另一个元素触发悬停事件

从另一个应用程序调用 iOS Safari 时会触发啥 Javascript 事件

从另一个小部件触发检查按钮悬停事件

我可以更改从另一个线程更改 ObservableCollections 后触发的 OnCollectionChanged 事件的顺序吗?