Javascript 为什么Backbone.js模型的新实例包含预定义默认值之外的其他值?
我使用Backbone.js创建复合表单字段,其中包含电话号码以及电话号码的类别。有两个视图:一个渲染复合字段see PhoneFieldView,另一个渲染包含字段see PhoneFieldSetView的字段集。fieldset视图还包含用于动态添加新电话字段的按钮 初始化PhoneFieldsetView时,它从DOM var window.Namecards.phone中的对象读取值。这是一个对象数组,包含用于填充初始化时设置的字段的值。例如,当重新加载表单时,如果电话字段验证失败,它将重新加载以前的值并添加错误css类。一个示例DOM对象是:Javascript 为什么Backbone.js模型的新实例包含预定义默认值之外的其他值?,javascript,backbone.js,Javascript,Backbone.js,我使用Backbone.js创建复合表单字段,其中包含电话号码以及电话号码的类别。有两个视图:一个渲染复合字段see PhoneFieldView,另一个渲染包含字段see PhoneFieldSetView的字段集。fieldset视图还包含用于动态添加新电话字段的按钮 初始化PhoneFieldsetView时,它从DOM var window.Namecards.phone中的对象读取值。这是一个对象数组,包含用于填充初始化时设置的字段的值。例如,当重新加载表单时,如果电话字段验证失败,它
window.Namecards.phone = [
{
value: '1111111',
type: 'work',
cssClass: ['form-field-error']
},
{
value: '222222',
type: 'home',
cssClass: ['form-field-error']
}
]
问题在于,当PhoneFieldsetView呈现给每个调用时
var phoneField = new PhoneField();
结果显示的实例如下所示:
phoneField = {
cssClass: ["phone-number", "form-field-error", "form-field-error"],
number: "111",
selectTypeElementName: "phone[type]",
textInputElementName: "phone[number]",
type: "home"
}
问题在于cssClass属性。如您所见,它包含两个表单字段错误字符串。结果表明,字符串“form field error”在数组cssClass中出现的次数等于window.Namecards.phone中的对象数。例如,如果window.Namecards.phone包含5项,则“表单字段错误”将在PhoneField的每个实例中出现5次
根据我的理解,当我打电话时,这让我感到困惑
var phoneField = new PhoneField();
我应该只有PhoneField模型的默认值。那么,为什么还要添加cssClass的这些附加值呢
当我在表单see PhoneFieldsetView.addNewField中添加一个新的空白字段时,也会发生同样的情况。当我创建PhoneField模型的新实例时,它还包含其他“form field error”cssClass值
我猜这是范围的问题,但我找不到源代码。下面是完整的代码
作用${
$document.readyfunction{
var PhoneField=Backbone.Model.extend{
默认值:{
textInputElementName:“电话[号码]”,
选择类型元素名称:“电话[类型]”,
编号:,
键入:“工作”,
cssClass:[“电话号码”]
}
};
var PhoneFields=Backbone.Collection.extend{
型号:PhoneField
};
var PhoneFieldView=Backbone.View.extend{
标记名:“div”,
活动:{
'单击a.delete-phone-number':'删除'
},
初始化:函数{
_.bindAllthis,'render','remove';
},
渲染:函数计数器{
var inputCssClass=this.model.get'cssClass.join';
这是$el.html+
+
“工作”+
“家”+
“其他”+
+
' ';
//选择默认选项。
这个.$'select option[value='+this.model.get'type'+']'.attr'selected','selected';
归还这个;
},
删除:函数{
//销毁与此视图关联的模型。
这个。模型。破坏;
//从DOM中删除此模型的视图。
这个.$el.remove;
}
};
var PhoneFieldsetView=Backbone.View.extend{
el:$'fieldset.phone',
活动:{
“单击按钮添加电话按钮”:“添加新字段”
},
初始化:函数{
var self=这个;
_.bindAllthis,'render','addField','addNewField','appendField','removeField';
这个计数器=0;
this.collection=新的电话字段;
//创建初始字段。设置变量window.Namecards.phone
//由服务器端控制器。请注意,这是在绑定之前添加的
//向集合添加事件。这将阻止追加字段
//两次;一次在初始化期间,一次在渲染期间。
如果window.Namecards.phone的类型!=“未定义”{
_.eachwindow.Namecards.phone,功能项,索引,列表{
self.addFielditem.value、item.type、item.cssClass;
};
}
//绑定要查看的集合事件。
this.collection.bind'add',this.appendField;
this.collection.bind'remove',this.removeField;
//渲染视图。
这个。呈现;
},
渲染:函数{
var self=这个;
此.$el.附加“电话”;
这.$el.append;
此.$el.附加“新”;
_如果集合不为空,则返回this.collection.models.eachfunctionitem{//
自我评价项目;
}这,;
},
//添加包含预定编号和类型的字段。
addField:函数编号、类型、cssClass{
var phoneField=新的phoneField;
console.logphoneField.attributes;
如果数字的类型!=='undefined'{
phoneField.set{
号码:号码
};
};
如果类型为类型!==“未定义”{
phoneField.set{
类型:类型
};
}
如果cssClass!==“未定义”&&cssClass.trim!=={
phoneField.get'cssClass'。pushcssClass;
}
this.collection.addphoneField;
},
//添加新的空字段。
addNewField:函数{
var phoneField=新的phoneField;
console.logphoneField.attributes;
this.collection.addphoneField;
},
appendField:functionitem{
//这似乎就是将模型绑定到视图的原因。
//在这种情况下,将PhoneField绑定到PhoneFieldView。
phoneFieldView=新的phoneFieldView{
型号:项目
};
这是$'phone-field'.appendphoneFieldView.renderthis.counter.el;
这个.counter++;
},
removeField:functionitem{
//如果已删除最后一个剩余字段,则创建一个新字段。
//这将确保始终至少存在一个字段。
如果this.collection.length==0{
这是addField;
}
}
};
//创建PhoneFieldView的实例。
var phoneFieldsetView=新的phoneFieldsetView;
};
}jQuery;
Backbone.js模型可以很好地处理值类型,但我不知道引用类型,因为我非常怀疑它是为此而设计的。排队
phoneField.get('cssClass').push(cssClass);
我有点认为每个模型实例都有一个来自默认值的对同一数组的引用,而cssClass中的任何值都会被推到这个位置。然后,当您声明一个新的PhoneField;,你当然会觉得奇怪。作为一个快速解决方案,我认为我会将模型的CSScCype属性更改为一个字符串,您将其视为序列化到它的数组。这应该不难做到,因为。不能用作css类,因此无论何时分配它,都要获取值并使用a.连接,当需要使用css类时,使用a.拆分。然后加入一个。主干网。js模型很适合值类型,但我不知道引用类型,因为我非常怀疑它是为此而设计的。排队
phoneField.get('cssClass').push(cssClass);
我有点认为每个模型实例都有一个来自默认值的对同一数组的引用,而cssClass中的任何值都会被推到这个位置。然后,当您声明一个新的PhoneField;,你当然会觉得奇怪。作为一个快速解决方案,我认为我会将模型的CSScCype属性更改为一个字符串,您将其视为序列化到它的数组。这应该不难做到,因为。不能用作css类,因此无论何时分配它,都要获取值并使用a.连接,当需要使用css类时,使用a.拆分。然后加入一个。基本上你是正确的,它们引用的是同一个数组,但是你应该能够重写它,这样每个数组都有自己的数组副本,请尝试在初始化构造函数中分配数组 你可能想看看这个问题
从本质上说,它们引用的是同一个数组,这是正确的,但是您应该能够重写它,以便每个数组都有自己的数组副本,请尝试在initialize构造函数中分配数组 你可能想看看这个问题
在理解了这个问题之后,我可以想出以下解决方案。诀窍是将函数指定给“defaults”属性,该属性返回模型的默认值。这样做会为PhoneField的每个实例创建一个单独的数组ccsClass实例 var PhoneField=Backbone.Model.extend{ 默认值:函数{ 返回{ textInputElementName:“电话[号码]”, 选择类型元素名称:“电话[类型]”, 编号:, 键入:“工作”, cssClass:[“电话号码”] }; } };
在理解了这个问题之后,我可以想出以下解决方案。诀窍是将函数指定给“defaults”属性,该属性返回模型的默认值。这样做会为PhoneField的每个实例创建一个单独的数组ccsClass实例 var PhoneField=Backbone.Model.extend{ 默认值:函数{ 返回{ textInputElementName:“电话[号码]”, 选择类型元素名称:“电话[类型]”, 编号:, 键入:“工作”, cssClass:[“电话号码”] }; } };
至于更普遍的解决办法,我必须承认我不确定可能是什么。我从未尝试过在字符串数组上使用主干集合。谢谢JayC。我终于解决了。原来我不理解新操作符在Javascript中是如何工作的。我认为引用类型的新实例(例如数组)是在创建包含引用类型的对象的新实例时创建的。现在我意识到情况并非如此。至于更普遍的解决方案,我必须承认我不确定它可能是什么。我从未尝试过在字符串数组上使用主干集合。谢谢JayC。我终于解决了。原来我不理解新操作符在Javascript中是如何工作的。我认为引用类型的新实例(例如数组)是在创建包含 引用类型。现在我意识到情况并非如此。