计算可观察值未更新 UI
Computed observable not updating UI
我的挖空网中的计算变量有问题。这是我的代码:
function ViewModel() {
var self = this;
self.seatsRaw = ko.observableArray([]);
self.selectedSeatId = ko.observable();
self.session = ko.observable();
self.seats = ko.computed(function(){
var seatsComplete= self.seatsRaw().slice(0);
for (var i = 0; i < seatsComplete.length; i++) {
if (self.selectedSeatId()) {
seatsComplete[i].selected = seatsComplete[i].id == self.selectedSeatId();
} else if (self.session () && Number(self.session ().seat) > 0) {
seatsComplete[i].selected = seatsComplete[i].id == self.sesion().seat;
} else {
seatsComplete[i].selected = false;
}
}
return seatsComplete;
});
self.selectSeat = function(data,event) {
self.selectedSeatId($(this).id);
};
}
所以,我刚收到一个带座位的数组,我想为数组中的每个 object 添加一个字段,以在 UI 中显示为 "selected"。
我从 ajax 中读取了 session 的信息和原始座位,当我更新它们时,我的 UI.
没有看到任何变化
为什么会这样?然后,我需要做什么来更新我的 UI?
谢谢!
编辑
<ul class="seats" data-bind="foreach: seats">
<li data-bind="css: {selected: selected, 'non-selected': !selected}, click: $root.selectSeat">
<a href="#" data-bind="attr: {id: id}">
<img data-bind="attr: {src: baseUrl + 'img/seats/' + image}" />
<p data-bind="text: name"></p>
</a>
</li>
</ul>
Seat 不是 ViewModel...应该是吗?
感谢您提供一些额外的背景信息。我会尝试更好地解释我在评论中的意思。
Seat is not a ViewModel... should it be?
即使 Seat
只是一个普通对象,它也是一种视图模型...这是您的代码中发生的事情(据我所知):
当您在计算中创建新数组时,它会填充与先前数组相同的对象。剔除渲染器看不到重新渲染列表项的理由。
看看这个例子。从日志中您可以看到所有内容 "working correctly",但敲除不会更新。在这个例子之后,我将展示如果我们让 selected
可观察会发生什么。
var seats =[
{ id: 1, selected: false },
{ id: 2, selected: true },
{ id: 3, selected: false }
];
var ViewModel = function() {
var self = this;
this.rawSeats = ko.observableArray(seats);
this.selectedSeatId = ko.observable(2);
this.selectSeat = function(data, event) {
self.selectedSeatId(data.id)
}
this.seats = ko.computed(function() {
var selectedId = self.selectedSeatId();
self.rawSeats().forEach(function(seat) {
seat.selected = seat.id === selectedId;
})
console.log(self.rawSeats());
return self.rawSeats();
});
}
ko.applyBindings(new ViewModel());
.selected { background: yellow }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: seats">
<li data-bind="css: { selected: selected },
text: id,
click: $root.selectSeat"></li>
</ul>
现在,具有可观察的属性:
var seats =[
{ id: 1, selected: ko.observable(false) },
{ id: 2, selected: ko.observable(true) },
{ id: 3, selected: ko.observable(false) }
];
var ViewModel = function() {
var self = this;
this.rawSeats = ko.observableArray(seats);
this.selectedSeatId = ko.observable(2);
this.selectSeat = function(data, event) {
self.selectedSeatId(data.id)
}
this.seats = ko.computed(function() {
var selectedId = self.selectedSeatId();
self.rawSeats().forEach(function(seat) {
seat.selected(seat.id === selectedId);
})
return self.rawSeats();
});
}
ko.applyBindings(new ViewModel());
.selected { background: yellow }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: seats">
<li data-bind="css: { selected: selected },
text: id,
click: $root.selectSeat"></li>
</ul>
我的挖空网中的计算变量有问题。这是我的代码:
function ViewModel() {
var self = this;
self.seatsRaw = ko.observableArray([]);
self.selectedSeatId = ko.observable();
self.session = ko.observable();
self.seats = ko.computed(function(){
var seatsComplete= self.seatsRaw().slice(0);
for (var i = 0; i < seatsComplete.length; i++) {
if (self.selectedSeatId()) {
seatsComplete[i].selected = seatsComplete[i].id == self.selectedSeatId();
} else if (self.session () && Number(self.session ().seat) > 0) {
seatsComplete[i].selected = seatsComplete[i].id == self.sesion().seat;
} else {
seatsComplete[i].selected = false;
}
}
return seatsComplete;
});
self.selectSeat = function(data,event) {
self.selectedSeatId($(this).id);
};
}
所以,我刚收到一个带座位的数组,我想为数组中的每个 object 添加一个字段,以在 UI 中显示为 "selected"。
我从 ajax 中读取了 session 的信息和原始座位,当我更新它们时,我的 UI.
没有看到任何变化为什么会这样?然后,我需要做什么来更新我的 UI?
谢谢!
编辑
<ul class="seats" data-bind="foreach: seats">
<li data-bind="css: {selected: selected, 'non-selected': !selected}, click: $root.selectSeat">
<a href="#" data-bind="attr: {id: id}">
<img data-bind="attr: {src: baseUrl + 'img/seats/' + image}" />
<p data-bind="text: name"></p>
</a>
</li>
</ul>
Seat 不是 ViewModel...应该是吗?
感谢您提供一些额外的背景信息。我会尝试更好地解释我在评论中的意思。
Seat is not a ViewModel... should it be?
即使 Seat
只是一个普通对象,它也是一种视图模型...这是您的代码中发生的事情(据我所知):
当您在计算中创建新数组时,它会填充与先前数组相同的对象。剔除渲染器看不到重新渲染列表项的理由。
看看这个例子。从日志中您可以看到所有内容 "working correctly",但敲除不会更新。在这个例子之后,我将展示如果我们让 selected
可观察会发生什么。
var seats =[
{ id: 1, selected: false },
{ id: 2, selected: true },
{ id: 3, selected: false }
];
var ViewModel = function() {
var self = this;
this.rawSeats = ko.observableArray(seats);
this.selectedSeatId = ko.observable(2);
this.selectSeat = function(data, event) {
self.selectedSeatId(data.id)
}
this.seats = ko.computed(function() {
var selectedId = self.selectedSeatId();
self.rawSeats().forEach(function(seat) {
seat.selected = seat.id === selectedId;
})
console.log(self.rawSeats());
return self.rawSeats();
});
}
ko.applyBindings(new ViewModel());
.selected { background: yellow }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: seats">
<li data-bind="css: { selected: selected },
text: id,
click: $root.selectSeat"></li>
</ul>
现在,具有可观察的属性:
var seats =[
{ id: 1, selected: ko.observable(false) },
{ id: 2, selected: ko.observable(true) },
{ id: 3, selected: ko.observable(false) }
];
var ViewModel = function() {
var self = this;
this.rawSeats = ko.observableArray(seats);
this.selectedSeatId = ko.observable(2);
this.selectSeat = function(data, event) {
self.selectedSeatId(data.id)
}
this.seats = ko.computed(function() {
var selectedId = self.selectedSeatId();
self.rawSeats().forEach(function(seat) {
seat.selected(seat.id === selectedId);
})
return self.rawSeats();
});
}
ko.applyBindings(new ViewModel());
.selected { background: yellow }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: seats">
<li data-bind="css: { selected: selected },
text: id,
click: $root.selectSeat"></li>
</ul>