我正在使用非官方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类选择器,选择在所有点击上收听事件。使用选择器,原始的,破碎的行为仍然存在,但没有它,播放器工作得很好。然而,我仍然不确定为什么这实际上有用,所以我为任何可以解释这一点的人提供赏金。
答案 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
方法。它能说清楚吗?