我试图使元素的文本根据是否被选择而变化,但是我很难弄清楚如何引用父对象来确定选择哪个对象。
我正在尝试的简化示例:
function Model(items){
this.items = ko.observableArray(items);
this.selectedItem = ko.observable();
this.dropDownText = function(item){
if(this.selectedItem()===item){
return item.name;
}else{
return item.dropDownText;
}
}
}
function Item(name, price){
this.name=name;
this.price=price;
this.dropDownText=name + ' ($' + price + ')';
this.dropDownTextFunction = function(item){
return item.name + ' ($' + item.price + ')';
}
}
var m = new Model([new Item('hammer', 5), new Item('nail', 0.03), new Item('tooth', 0.6)]);
m.selectedItem(m.items()[1]);
ko.applyBindings(m);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<select data-bind="options: items(), value: selectedItem, optionsText: 'dropDownText'"></select>
<span data-bind="text: selectedItem().price"></span>
价格不应显示在所选元素中,而应显示在其他元素中。
我试过的
'dropDownText'-非函数变量可以正常工作,但这不能解决问题
'dropDownTextFunction'-在下拉列表中显示函数的代码,也无法获取父对象
'dropDownTextFunction()'-结果为空的选项文本,再次无法获取父对象
'$ parent.dropDownText'-也导致空选项文本
最佳答案
这是一种解决方案,但不是我希望在我的ko应用程序中实现的一种解决方案。
function Model(items){
var self = this;
self.items = ko.observableArray(items);
self.selectedItem = ko.observable();
self.selectedItem.subscribe(function() {
console.log('Selected');
items.forEach(function(it) {
if (it === self.selectedItem()) {
it.dropDownText(it.name);
} else {
it.dropDownText(it.name + ' ($' + it.price + ')');
}
});
});
return self;
}
function Item(name, price){
this.name=name;
this.price=price;
this.dropDownText= ko.observable(name + ' ($' + price + ')');
}
var m = new Model([new Item('hammer', 5), new Item('nail', 0.03), new Item('tooth', 0.6)]);
m.selectedItem(m.items()[1]);
ko.applyBindings(m);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<select data-bind="options: items(), value: selectedItem, optionsText: 'dropDownText'"></select>
<span data-bind="text: selectedItem().price"></span>
完全必要的一件事是
dropDownText
是可观察的,以便显示的文本在更改时可以更新。您的原始代码中缺少该代码。我不喜欢的部分是,每当选定值更改时,就必须计算整个列表的可观察值。
一种替代方法是修改item对象和订阅,这使它更加简洁:
function Model(items){
var self = this;
self.items = ko.observableArray(items);
self.selectedItem = ko.observable();
self.selectedItem.subscribe(function() {
items.forEach(function(it) {
it.selected(it === self.selectedItem())
});
});
return self;
}
function Item(name, price){
var self = this;
self.name = name;
self.price = price;
self.selected = ko.observable(false);
self.dropDownText = ko.computed(function() {
return this.selected()
? this.name : this.name + ' ($' + this.price + ')';
},self);
return self;
}
但是我真正希望的是让ViewModel处理项目的整个创建和管理。您可以使用可以像
model.addItem(name,price)
这样的函数调用的模型,也可以像这样的additems([{name: '', price:1}, ...])
那样调用函数。如果您尝试使用此路径,您会发现实现视图模型非常清晰和容易,因为该模型需要注意自身及其所有组件。如果您想在其他代码中使用cosntructor,也可以在模型中公开它。注意:
var self=this
模式简化了在模型的其他函数中使用this
的工作,例如计算出的可观测值