我真的很喜欢Backbone,但我最难做的事情似乎很简单。感谢以下示例的任何帮助。
我有一个模型,Criteria,我想用它来存储我的UI中的一些项目的状态。有一些简单的属性,一个属性是一个ID数组,用于存储用户在UI中选择的标记的ID。
所以,我创建了一个新实例。我在tags数组中添加了一些项目。然后,我想重新开始,创建一个新实例,分配给同一个变量。但是,我的标签数组继续保存我作为第一个Criteria实例的一部分添加的信息。
我已经记录了下面的测试用例。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<script src="Scripts/Libraries/jquery-1.6.1.js" type="text/javascript"></script>
<script src="Scripts/Libraries/underscore.js" type="text/javascript"></script>
<script src="Scripts/Libraries/backbone.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
$(function () {
// Simple model to hold some state about my UI.
var Criteria = Backbone.Model.extend({
defaults: {
"status": "Normal",
"priority": "Normal",
"tags": new Array()
}
});
// Create new criteria.
window.criteria = new Criteria();
// The length of the tags array should be 0. PASSES
console.log("Expect 0: Actual " + window.criteria.get("tags").length);
// Add a tag id to the tags array.
window.criteria.get("tags").push(5); // Tag with ID of 5.
// The length of the tags array should be 1. PASSES
console.log("Expect 1: Actual " + window.criteria.get("tags").length);
// Create a new instance of criteria.
window.criteria = new Criteria();
// The length of the tags array should be 0. FAILS
// CONFUSED. I thought this is now a new instance with a new set of attributes.
// Why does the tags collection still have an item in it.
console.log("Expect 0: Actual " + window.criteria.get("tags").length);
// OK. So, I will call the clear method on the model. This is supposed to remove all attributes
// from the model.
// Then, I will create it again.
window.criteria.clear();
window.criteria = new Criteria();
// The length of the tags array should be 0. FAILS. Still 1.
console.log("Expect 0: Actual " + window.criteria.get("tags").length);
// ARGH!
console.log("HELP!");
});
</script>
</head>
<body>
<h1>Test</h1>
<p>Backbone test page.</p>
</body>
</html>
我是不是在这里?我是否尝试使用Backbone来实现它的目的?或者我在javascript OO编程中遗漏了一些更通用的东西?
P.S。我最初使用了Backbone标签集合,但是它提出了一系列不同的问题,这些问题与多个集合中引用的Tag模型有关,以及当从任何集合中删除项目时,Backbone的remove方法如何取消设置“集合”引用。另一天,另一个问题。
答案 0 :(得分:70)
“默认值”也可以是一个功能。
var Criteria = Backbone.Model.extend({
defaults: function () {
return {
"status": "Normal",
"priority": "Normal",
"tags": new Array()
}
}
});
当实例化新Criteria时,这将创建一个新数组。 请参阅:http://backbonejs.org/#Model-defaults
答案 1 :(得分:34)
Thom Blake对于为什么它保持数组的相同值是正确的。解决此问题的一个选项是在初始值设定项中设置默认值
var Criteria = Backbone.Model.extend({
defaults: {
"status": "Normal",
"priority": "Normal"
},
initialize: function(){
if( !this.get('tags') ){
this.set({tags: new Array()});
}
}
});
答案 2 :(得分:13)
在“默认值”下定义“标记”时,您将创建一个新数组并将其设置为该类的默认值。然后,当您创建一个新实例时,它具有相同的Array引用,它仍然包含您推送到它的内容。
您可以在第一次使用之前将其设置为[]
,而不是为标记设置默认值:
window.criteria = new Criteria()
window.criteria.set({'tags', []}) //you can use new Array() if you want
window.criteria.get('tags').push(5)
window.criteria = new Criteria()
console.log(window.criteria.get('tags')) //should be undefined
window.criteria.set({'tags', []})
答案 3 :(得分:3)
要明确的是,Maksym H.提供的最后一个选项无法解决问题。假设所有设置的值都是不可变的,则提供defaults属性。但是,数组是可变的,这意味着它的值可以改变(例如,标签[0] =“你好”可以用标签[0] =“hi there”改变。)
通过使用btford的答案,您正在强制在模型的每个新实例上创建任何可变对象/属性的新实例,因此它永远不会被共享,因为该对象是使用函数范围变量创建的。
同样,Derick Bailey的答案是正确的,它只是使用initialize方法而不是默认方法。