我正在使用非官方的mpdjs库和backbone.js为mpd音乐守护进程编写一个浏览器内远程。collectionView图书馆。数据通过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首歌曲,则单击n次后页面将停止侦听事件。
更新:我似乎意外地修复了这个问题与一些布局的变化。我修改了视图,以便在渲染时插入一个tr而不是插入一个div:
App.Views.PlayerView = Backbone.View.extend
tagName: 'tr'
template: _.template(JST.player())
events:
'click': 'changeSong'
和我拿走了.song类选择器,选择在所有点击时侦听事件。有了选择器,原始的、破碎的行为仍然存在,但没有选择器,玩家就能很好地工作。然而,我仍然不确定为什么这真的有效,所以我悬赏任何能解释这一点的人。
这是你的视图
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首歌,一次点击其中的4首&然后在没有点击之后将触发changeSong
方法。