#backbone.js #websocket
#backbone.js #websocket
Вопрос:
Я пишу встроенный в браузер пульт дистанционного управления для демона mpd music, используя неофициальную библиотеку mpdjs и backbone.js с помощью библиотеки backbone.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 нажатий.
Обновление: похоже, я случайно исправил эту проблему с помощью нескольких изменений макета. Я изменил представление так, чтобы вместо вставки div при рендеринге вставлялся tr:
App.Views.PlayerView = Backbone.View.extend
tagName: 'tr'
template: _.template(JST.player())
events:
'click': 'changeSong'
и я убрал .выбор класса песни, позволяющий прослушивать событие при всех щелчках мыши. С селектором исходное, нарушенное поведение все еще сохраняется, но без него проигрыватель работает очень хорошо. Однако я все еще не уверен, почему это на самом деле сработало, поэтому я предлагаю вознаграждение любому, кто может это объяснить.
Ответ №1:
Это ваше мнение
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
вы удаляете classname song
. Следовательно, обработчик события запускается только один раз! потому что после его запуска имя класса song
удаляется.
Итак, если у вас есть примерно 4 песни, щелкните четыре из них один раз, а затем, после того, как ни один из щелчков не запустит changeSong
метод. Проясняет ли это ситуацию?