在backbone.js中,我如何将keyup事件绑定到文档?

6

我一直在跟随Railscast教程学习backbone.js,并想扩展其功能以包括键盘控制。我将以下内容添加到我的show视图:

class Raffler.Views.EntryShow extends Backbone.View
  template: JST['entries/show']

  events:
    'click .back': 'showListing'
    'keyup': 'goBack'

  showListing: ->
    Backbone.history.navigate("/", trigger: true)

  goBack: (e) ->
    console.log e.type, e.keyCode

  render: ->
    $(@el).html(@template(entry: @model))
    this

在我的展示模板中,我有以下内容:
<a href="#" class="back">Back</a>
<%= @entry.get('name') %></td>

如果我使用Tab键选择后退链接,然后开始随机按键,我会在我的JavaScript控制台中得到输出。但是,如果我加载页面而不选择链接,只是开始按键,我的控制台中没有输出。
如何将事件绑定到文档,以便在加载屏幕时监听任何按键?

1
可能是重复的问题:backbone.js - 使用输入框中的值过滤集合 - mu is too short
这个功能是一样的,但我怀疑它会被视为重复。这个人特别询问如何绕过视图的范围,在文档中绑定一个键盘抬起事件而不是单个输入。文档很可能在视图范围之外。在他自己的示例中,他只绑定了 'keyup',这意味着他将其绑定到视图的容器元素,这很可能不是整个页面。 - Sander
2个回答

6

在处理像这样的情况时,您需要绕过backbone视图的作用域:

  events:
    'click .back': 'showListing'
    'keyup': 'goBack'

您正在将goBack函数绑定到视图容器元素上触发的keyup事件上。(默认情况下,是呈现视图的div元素)

如果您想要绑定到视图之外的某个东西上(它没有自己的视图!(*)),那么不要这样做。

Raffler.Views.EntryShow = Backbone.View.extend({
  template: JST['entries/show'],

  events: {
    'click .back': 'showListing'
  },

  initialize: function () {
    $('body').keyup(this.goBack);
  },

  showListing: function () {
    Backbone.history.navigate("/", trigger: true);
  },

  goBack: function (e) {
    console.log e.type, e.keyCode;
  },

  render: function () {
    $(this.el).html(this.template(entry: @model));
    return this;
  }

});

(*)备注 如上所述,只有在您要绑定的项目没有自己的视图时才最好这样做,如果您有一个用于全页的视图(应用程序视图或类似视图),则可以在那里绑定keyup,并触发事件App.trigger('keypressed', e); 例如。

然后,您可以在EntryShow视图中绑定该App的keypressed事件。

App.bind('keypressed', goBack);

请记住,在某些情况下,您应该将某些操作作为延迟事件或分组按键一起执行,而不是在整个页面上触发每个按键事件,这可能会对性能造成很大影响,特别是在旧版浏览器上。


这在视图的初始加载时对我有效。但是当用户第二次导航到该视图时,绑定将被重新应用,并且该方法将在每个“keyup”事件上触发两次。 - wuliwong
你可以用两种方法解决这个问题,一种是使用视图管理器,比如backbone marionette(或者自己编写的),并在视图关闭时取消绑定keypressed事件。另一种方法是保留绑定,但使用一些处理过的状态。当你绑定到keypressed事件时,只需要绑定一次,检查容器上是否有keypressedprocessed类。如果没有,则绑定它,否则就不要绑定。(绑定后,你必须设置类,这样第二次访问时就不会再次绑定了。) - Sander

4
您的事件将被限制在视图元素@el中。如果要捕获document上的事件,您需要自己处理:
initialize: ->
  $(document).on "keyup", @goBack

remove: ->
  $(document).off "keyup", @goBack

做这个技巧应该没问题了。

1
这个答案解决了绑定的移除问题,但是 remove() 不会自动调用,对吗?你需要一个在用户导航离开视图时被调用的东西。相反,我只是确保在应用当前视图之前删除任何先前的绑定。这有点 hacky,但它能够工作。 - wuliwong
@wuliwong 是的,我认为 remove() 不会自动调用。当用户从视图导航离开时,有哪个与 initialize 相反且会自动调用的函数?我在文档中找不到这样的函数。有什么解决方案吗? - mc9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接