Я не могу понять, почему в моем приложении Backbone (приложение Todo) после перезагрузки страницы (CTRL + F5) метод filterTodos
не вызывается. Когда я просто нажимаю на ссылки для фильтрации Todos («Активный», «Завершенный») - он вызывается.
Вы можете увидеть эту функцию по ссылкам ниже. Независимо от того, сколько раз вы нажимаете Обновить в браузере - отображаются правильные отфильтрованные результаты:
http://todomvc.com/architecture-examples/backbone/#/completed
http://todomvc.com/architecture-examples/backbone/#/active
У меня есть теория, что это потому, что я слишком рано инициирую filter
событие из Router
- TodosView
еще не инициализирован и, следовательно, он еще не выполняет событие listenTo filter
.
Но как Router
может сообщить View
о необходимости повторного рендеринга (на основе фильтра), если этот View
еще не существует? Разве этого нельзя добиться, запустив какое-то событие в Router
, как это делаю я? Один из возможных вариантов - иметь глобальную переменную app.FilterState
.
Существуют ли другие способы связи между маршрутизатором и еще не созданным View?
Для app.FilterState
я установлю его состояние в Router
, а затем проверю его в просмотре и вызову функцию filterTodos
вручную, вот так, и она будет работать:
views / todos.js
render: function() {
app.Todos.each(function(todo) {
this.renderTodo(todo);
}, this);
if (app.FilterState !== 'all') { // <--- ADDED CODE
this.filterTodos(app.FilterState);
}
return this;
}
Существующий исходный код:
routers / router.js
var app = app || {};
var Router = Backbone.Router.extend({
routes: {
'all': 'all',
'active': 'active',
'completed': 'completed'
},
all: function() {
console.log('all');
app.Todos.trigger('filter', 'all');
},
active: function() {
console.log('active');
app.Todos.trigger('filter', 'active');
},
completed: function() {
console.log('completed');
app.Todos.trigger('filter', 'completed');
}
});
app.Router = new Router();
Backbone.history.start();
views / todos.js
var app = app || {};
app.TodosView = Backbone.View.extend({
el: '#todo-list',
initialize: function(todos) {
console.log('initialize begin');
app.Todos.reset(todos);
this.listenTo(app.Todos, 'add', this.addOneTodo);
this.listenTo(app.Todos, 'filter', this.filterTodos);
this.render();
console.log('initialize end');
},
render: function() {
app.Todos.each(function(todo) {
this.renderTodo(todo);
}, this);
return this;
},
renderTodo: function(todo) {
var todoView = new app.TodoView({model: todo});
this.$el.append(todoView.render().el);
},
addOneTodo: function(todo) {
this.renderTodo(todo);
},
filterTodos: function(filterType) {
console.log('filter'); // <--- CODE DOES NOT REACH THIS LINE WHEN CALLED ON BROWSER'S REFRESH (F5)
var active = app.Todos.active();
var completed = app.Todos.completed();
if (filterType === 'active') {
// hide remaining
_.each(completed, function(todo) {
todo.trigger('hide');
});
//show active
_.each(active, function(todo) {
todo.trigger('show');
});
}
else if (filterType === 'completed') {
_.each(completed, function(todo) {
todo.trigger('show');
});
//show active
_.each(active, function(todo) {
todo.trigger('hide');
});
}
else if (filterType === 'all') {
app.Todos.each(function(todo) {
todo.trigger('show');
});
}
}
});