在n次事件触发后,Backbone停止侦听事件

时间:2014-07-06 18:02:03

标签: backbone.js websocket

我正在使用非官方mpdjs library和backbone.js以及backbone.collectionView库为mpd音乐守护程序编写一个浏览器内远程控制器。数据通过websockets在浏览器和服务器之间传输。

以下代码块控制事件触发:

App.Views.PlayerView = Backbone.View.extend
  template: _.template(JST.player())
  events:
    'click .song': 'changeSong'

  changeSong: (e) ->
    classList = e.currentTarget.classList
    classList.remove('song')
    classList.remove('ui-sortable-handle')

    songId = classList[0]
    socket.send("play-song:#{songId.split('-')[1]}")

  render: () ->
    emp = @model.toJSON()
    html = @template(emp)
    html = $(html).addClass("song song-#{emp.id}")[0]
    @$el.append(html)

App.Views.PlaylistView = new Backbone.CollectionView
  el: $('.queue')
  selectable: true
  collection: App.CurrentPlaylist
  modelView: App.Views.PlayerView

这些是相关的模型和集合:

App.Models.Song = Backbone.Model.extend
  defaults:
    track: ''
    title: ''
    artist: ''
    album: ''
    length: ''

App.Collections.Playlist = Backbone.Collection.extend
  model: App.Models.Song
App.CurrentPlaylist = new App.Collections.Playlist

当应用程序启动并连接到WebSocketServer时,以下代码将填充以下标记:

 // this is wrapped in socket.onmessage, and is only called once
  parseTime = (time) ->
    min = Math.floor(parseInt(time, 10) / 60)
    sec = Math.floor(parseInt(time, 10) % 60)
    if sec < 10
      sec = "0#{sec}"
    "#{min}:#{sec}"

  for key, value of data.playlist
    song = new App.Models.Song(
      id: value.Id
      track: value.Track.split('/')[0]
      title: value.Title
      artist: value.Artist
      album: value.Album
      length: parseTime(value.Time)
    )
    App.CurrentPlaylist.add(song)

  App.Views.PlaylistView.render()

// this is the markup it spits out
<table class="queue pure-table collection-list selectable" tabindex="0">
  <div data-model-cid="c3">
    <tr class="song song-1">
      <td>3</td>
      <td>Reykjavik Blues</td>
      <td>Inf</td>
      <td>The Go Round</td>
      <td>2:06</td>
      </tr>
  </div>
  <div data-model-cid="c4">
    <tr class="song song-2">
      <td>5</td>
      <td>Wasting Time</td>
      <td>Inf</td>
      <td>The Go Round</td>
      <td>2:30</td>
    </tr>
  </div>
</table>

当'play-song-2'被发送到服务器时,调用以下函数。 '2'被解析出'play-song-2',所以这个功能正常工作。

function playSong(ws, songId) {
  mpdConnection.sendCommand('playid ' + songId, function(err, msg) {
    if (err) throw err;

    // this is a helper function that takes the plain text response
    // and organizes it into a javascript object
    msg = msgToObject(msg);  
    msg.type = 'song-update';
    ws.send(JSON.stringify(msg));
  });
}

然而,我遇到的问题是,在加载页面时,changeSong(e)几乎在.song被点击后立即触发。但是,如果页面上有大量歌曲,则页面会在n次点击后停止收听事件。

更新:我似乎偶然通过一些布局更改修复了此问题。我修改了视图,以便在渲染时插入tr而不是插入div:

App.Views.PlayerView = Backbone.View.extend
  tagName: 'tr'
  template: _.template(JST.player())
  events:
    'click': 'changeSong'

我拿走了.song类选择器,选择在所有点击上收听事件。使用选择器,原始的,破碎的行为仍然存在,但没有它,播放器工作得很好。然而,我仍然不确定为什么这实际上有用,所以我为任何可以解释这一点的人提供赏金。

1 个答案:

答案 0 :(得分:0)

这是您的观点

App.Views.PlayerView = Backbone.View.extend
  events:
    'click .song': 'changeSong'

  changeSong: (e) ->
    classList = e.currentTarget.classList
    classList.remove('song')
    # your logic

现在根据您的events哈希,只要点击了类名song的元素,就会执行方法changeSong。但是在changeSong内你删除了类名song。因此,事件处理程序只运行一次!因为一旦它运行,类名song就被删除了。

所以如果你有4首歌曲,请点击其中的四首歌曲。然后,没有任何点击将触发changeSong方法。它能说清楚吗?