gpt4 book ai didi

javascript - 为什么 Backbone.Collection 对第一个查看者显示两次?

转载 作者:行者123 更新时间:2023-12-03 10:53:35 25 4
gpt4 key购买 nike

我尝试通过修改 Todo 演示在同一页面的两个不同查看器中显示相同的数据。任何数据更改都会反射(reflect)在两个查看器中。该代码适用于唯一的一个查看器,但在使用 fetch 重新加载页面后显示了我不想要的结果。待办事项列表在第一个查看者中显示两次,并且一半的结果失去了绑定(bind)事件。有人可以帮助我吗?提前致谢。

The code can be played with the jsfiddle.

HTML:

<div id="todoapp">


<header>
<h1>Todos</h1>
<input class="new-todo" type="text" placeholder="What needs to be done?">
</header>

<section class="main">
<input id=toggle-all class="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list"></ul>
</section>

<footer>
<a class="clear-completed">Clear completed</a>
<div class="todo-count"></div>
</footer>

</div>


<div id="todoapp2">

<header>
<h1>Todos</h1>
<input class="new-todo" type="text" placeholder="What needs to be done?">
</header>

<section class="main">
<input id=toggle-all-2 class="toggle-all" type="checkbox">
<label for="toggle-all-2">Mark all as complete</label>
<ul class="todo-list"></ul>
</section>

<footer>
<a class="clear-completed">Clear completed</a>
<div class="todo-count"></div>
</footer>

</div>

<div id="instructions">
Double-click to edit a todo.
</div>

<!-- Templates -->

<script type="text/template" id="item-template">
<div class="view">
<input class="toggle" type="checkbox" <%= done ? 'checked="checked"' : '' %> />
<label><%- title %></label>
<a class="destroy"> Destroy </a>
</div>
<input class="edit" type="text" value="<%- title %>" />
</script>

<script type="text/template" id="stats-template">
<% if (done) { %>
<a class="clear-completed">Clear <%= done %> completed <%= done == 1 ? 'item' : 'items' %></a>
<% } %>
<div class="todo-count"><b><%= remaining %></b> <%= remaining == 1 ? 'item' : 'items' %> left</div>
</script>

JS:

$(function () {

Todo = Backbone.Model.extend({

defaults: function() {
return {
title: "empty todo...",
order: Todos.nextOrder(),
done: false
};
},

toggle: function() {
this.save({done: !this.get("done")});
}

});

TodoList = Backbone.Collection.extend({

model: Todo,
localStorage: new Backbone.LocalStorage("todos-backbone"),

done: function() {
return this.where({done: true});
},

remaining: function() {
return this.where({done: false});
},

nextOrder: function() {
if (!this.length) return 1;
return this.last().get('order') + 1;
},

comparator: 'order'

});


var Todos = new TodoList;


TodoView = Backbone.View.extend({

tagName: "li",

template: _.template( $('#item-template').html() ),

events: {
"click .toggle" : "toggleDone",
"dblclick .view" : "edit",
"click a.destroy" : "clear",
"keypress .edit" : "updateOnEnter",
"blur .edit" : "close"
},

initialize: function() {

this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'destroy', this.remove);
},

render: function() {

this.$el.html( this.template(this.model.toJSON()) );

this.$el.toggleClass('done', this.model.get('done') );

this.input = this.$('.edit');
//alert(this.input.val() );


return this;
},

toggleDone: function() {
this.model.toggle();
},

edit: function() {
this.$el.addClass("editing");
this.input.focus();
},

close: function() {
var value = this.input.val();
if (!value) {
this.clear();
} else {
this.model.save({title: value});
this.$el.removeClass("editing");
}
},

updateOnEnter: function(e) {
if (e.keyCode == 13) this.close();
},

clear: function() {
this.model.destroy();
}

});

var AppView = Backbone.View.extend({

//el: $("#todoapp"),

statsTemplate: _.template($('#stats-template').html()),

events: {
"keypress .new-todo": "createOnEnter",
"click .clear-completed": "clearCompleted",
"click .toggle-all": "toggleAllComplete"
},

initialize: function() {

this.input = this.$(".new-todo");
this.allCheckbox = this.$(".toggle-all")[0];

this.listenTo(Todos, 'add', this.addOne);
this.listenTo(Todos, 'reset', this.addAll);

this.listenTo(Todos, 'all', this.render);

this.footer = this.$('footer');
this.main = this.$('.main');

//Todos.fetch();
Todos.fetch({reset:true});

},

render: function() {
var done = Todos.done().length;
var remaining = Todos.remaining().length;

if (Todos.length) {
this.main.show();
this.footer.show();
this.footer.html(this.statsTemplate({done: done, remaining: remaining}));
} else {
this.main.hide();
this.footer.hide();
}

this.allCheckbox.checked = !remaining;
},

addOne: function(todo) {
var view = new TodoView({model: todo});
//console.log(view.render().el );

//this.$(".todo-list").append( view.render().el );
this.$(".todo-list").append( view.render().el );
console.log( this.main.parent() );
},

addAll: function() {
Todos.each(this.addOne, this);
},

createOnEnter: function(e) {
if (e.keyCode != 13) return;
if (!this.input.val()) return;

Todos.create({title: this.input.val()});
this.input.val('');
},

clearCompleted: function() {
_.invoke(Todos.done(), 'destroy');
return false;
},

toggleAllComplete: function () {
var done = this.allCheckbox.checked;
Todos.each(function (todo) { todo.save({'done': done}); });
}

});

var app1 = new AppView({ el: $("#todoapp") });

var app2 = new AppView({ el: $("#todoapp2") });

});

最佳答案

原因是您只为这两个 View 使用一个集合。

  • 最初创建 app1 并初始化您获取的集合,并且仅由 app1 监听触发事件
  • 现在创建了第二个 View 并再次获取集合,但现在 app1 和 app2 中都会监听集合触发的重置事件,并且两者都会呈现

要解决这个问题,您可以在两个 View 初始化后仅获取一次集合。

working fiddle

关于javascript - 为什么 Backbone.Collection 对第一个查看者显示两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28341608/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com