Ваш подход не совсем соответствует архитектуре Backbone. В Магистрали ты
смоделируйте свою бизнес-область как Модели и Коллекции Моделей. Если вы следуете
В этом правиле все становится на свои места довольно красиво.
Решение назвать вашу модель Table
неверно в этом контексте, так как таблица
представительский объект. Сами данные могут отображаться разными способами.
Ниже приведен пример того, как приложение может (или должно) быть разработано в
способ, который не работает против Backbone.js. Данные моделируются как коллекция
элементов, каждый элемент будет представлен в строке таблицы.
Пожалуйста, следуйте комментариям в исходном коде для дальнейшего объяснения.
Файл: index.html (я создаю приложение, используя npm и browserify, который не
показано здесь. Обязательно укажите необходимые зависимости).
<!doctype html>
<html>
<head>
<title>Coffeescript And Backbone</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h2>Elements Table</h2>
<div class="table"></div>
</div>
<script id="tablerow" type="text/x-handlebars-template">
<td>{{id}}</td>
<td>{{name}}</td>
<td>{{value}}</td>
<td><button class="button">HaveDataBytes</button></td>
</script>
<script src="app.js"></script>
</body>
</html>
Файл: app.coffee
# The template is integrated in index.html (script#tablerow).
# Here I read and compile the template function for the table row.
#
# This must be called after the template script is in the DOM.
#
# Using a packaging tool like browserify or webpack would allow you
# to precompile the templates during the packaging process, but this
# approach is good for small applications.
compileTemplate = (name) ->
source = document.getElementById(name).innerHTML
Handlebars.compile(source)
rowTemplate = compileTemplate('tablerow')
# Define the applications backbone
App =
View: {}
Model: {}
Collection: {}
# This is a dummy dataset of elements that would be fetched from the server
# using the Collection abstraction. Each entry in data will be represented
# in a table view further down.
data = [
{ id: 1, name: "element1", value: "value1", haveDataBytes: true },
{ id: 2, name: "element2", value: "value2", haveDataBytes: false },
{ id: 3, name: "element3", value: "value3", haveDataBytes: true },
{ id: 4, name: "element4", value: "value4", haveDataBytes: true },
{ id: 5, name: "element5", value: "value5", haveDataBytes: false }
]
# The model element takes up each entry from data ...
class App.Model.Element extends Backbone.Model
# and is stored in a collection of Element models
class App.Collection.Elements extends Backbone.Collection
model: App.Model.Element
По сравнению с вашим подходом с простыми списками для заголовков и столбцов в модели
Основным преимуществом является то, что все данные хранятся и контролируются Backbone.
Вы можете просто обновить всю коллекцию, прослушать изменения и отправить события,
сериализовать отдельные записи на сервер, реагировать на изменения отдельных записей -
полный контроль ...
# The table view
class App.View.ElementsTable extends Backbone.View
# is a table by itself
tagName: 'table'
# it receives the collection of elements
initialize: (options) ->
@collection = options.collection
# and renders each row ...
render: ->
@collection.each(@renderRow, @)
@
# ... in a element table row view
renderRow: (row) ->
rowView = new App.View.ElementTableRow(model: row)
@$el.append(rowView.render().el)
# The element table row ...
class App.View.ElementTableRow extends Backbone.View
# ... is itself a row
tagName: 'tr'
# and takes an element model
initialize: (options) ->
@model = options.model
# it handles the click event ...
events: {
'click button': 'click'
}
# ... with full access to the model and the collection, which is a member
# of the element model
click: (evt) ->
console.log(evt.target.name, @model, @model.collection)
@$('td').toggleClass('red')
# render uses the precompiled handlebars template to render the row,
# no HTML in the view or the model necessary
render: () ->
@$el.html(rowTemplate(this.model.toJSON()))
# Here I show/hide the buttons based on the element models data.
# It would definitely be better to not render the buttons in first place
if not @model.get('haveDataBytes')
@$('button').hide()
@
# simple start script
$(() ->
# 'load' the data as a collection
collection = new App.Collection.Elements(data)
# check the elements
console.log(collection.models)
# create and render the table view
view = new App.View.ElementsTable(collection: collection)
$('.table').append(view.render().el)
)
И последнее, но не менее важное: doFunction
должно жить в представлении (см. click
в
App.View.ElementTableRow
) или вызываться обработчиком щелчка App.View.ElementTableRow
.