如何订阅 observableArray 项目的更改
Posted
技术标签:
【中文标题】如何订阅 observableArray 项目的更改【英文标题】:How to subscribe to change in observableArray's item 【发布时间】:2020-10-01 23:04:06 【问题描述】:我在这里准备了一个基本的 knockout.js 小提琴:http://jsfiddle.net/utm02ohk/2/
为了完整起见,我将在这里重复部分代码:
在我看来,我有 foreach 循环,它遍历一个 observableArray 的项目:
<div data-bind="foreach: $root.availableItems">
<div class="switchBox">
<div class="switchName"><strong data-bind="text: ' ' + name()"></strong></div>
<label class="Switch">
<input type="checkbox" data-bind="checked: state">
</label>
</div>
</div>
它基本上遍历了我的 availableItems 数组中的元素:
self.availableItems([
new Item(1, "item1", state1, self.onItemStateChange),
new Item(2, "item2", state2, self.onItemStateChange),
new Item(3, "item3", state3, self.onItemStateChange)
]);
如你所见,我还有一个函数,我用 observables 初始化每个项目:
function Item(id, name, state, onChange)
var self = this;
self.id = ko.observable(id);
self.name = ko.observable(name);
self.state = ko.observable(state);
self.state.subscribe(function(newValue)
onChange(self, newValue);
);
数组中的每个项目都有状态变量(state1、state2、state3),它们是布尔值,它们控制检查哪个复选框,哪个不检查。它们(为了这个例子)设置在 ViewModel 的开头:
var state1 = true;
var state2 = false;
var state3 = false;
实际上 state1、state2 和 state3 是从服务器映射的。我想要实现的是,在我用起始状态值初始化我的项目后,我希望它们在 state1、state2 和 state3 的每次更改时被订阅,以便根据从服务器收到的值选中或不选中复选框.
目前,它们在第一次初始化后没有被更改。我需要尽可能减少对现有代码方法的更改,因为它会影响原始代码中的许多其他内容。
这可能吗,如果可以,有人可以解释一下如何在 knockout.js 中编写代码吗?
【问题讨论】:
【参考方案1】:如果我理解正确,我认为这将解决您的问题,只需对您现有的代码进行很少的更改: https://jsfiddle.net/sr3wy17t/
function Item(id, name, state, onChange)
var self = this;
self.id = ko.observable(id);
self.name = ko.observable(name);
self.state = ko.observable(state);
self.state.subscribe(function(newValue)
onChange(self, newValue);
);
function ViewModel()
var self = this;
var state1 = true;
var state2 = false;
var state3 = false;
self.availableItems = ko.observableArray([]);
self.activeItemss = ko.computed(function()
return self.availableItems().filter(function(item)
return item.state();
);
);
self.onItemStateChange = function(item, newValue)
console.log("State change event: " + item.name() + " (" + newValue + ")");
;
self.init = function()
self.availableItems([
new Item(1, "item1", state1, self.onItemStateChange),
new Item(2, "item2", state2, self.onItemStateChange),
new Item(3, "item3", state3, self.onItemStateChange)
]);
setInterval(() =>
var itemNoThatChanged = Math.floor(Math.random() * 3);
var newState = Math.random() > 0.5;
self.availableItems()[itemNoThatChanged].state(newState)
, 1000)
;
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
viewModel.init();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="foreach: $root.availableItems">
<div class="switchBox">
<div class="switchName"><strong data-bind="text: ' ' + name()"></strong></div>
<label class="Switch">
<input type="checkbox" data-bind="checked: state">
</label>
</div>
</div>
(在 setInterval 函数中,您应该有一个 ajax 调用来获取更新的值)
【讨论】:
感谢您的回复。如果一个状态是另一个 ViewModel 的一部分,这会起作用吗?我可以将 pureComputed 用于 activeItems 而不是计算的吗? 我对这两个问题都这么认为——如果你有问题,那就做一个小提琴并在这里发布 感谢您的回答,但不幸的是,这并不是我的意思。我想对其进行编码,以便仅更改为 state1、state2 或 state3 会导致复选框对应新状态。您正在直接更改数组中的项目,这不是我收到服务器响应后的情况。你能帮忙吗?以上是关于如何订阅 observableArray 项目的更改的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Knockout.js 在特定位置将项目添加/插入到 ObservableArray
如何使用 Knockout-Validation 将无效项目添加到 observableArray 以使 validObservable 无效
如何处理绑定:更改 observableArray 中的数据后的 foreach
在 knout.js 中遍历 observablearray 时,如何检索 foreach 的 ko.computed 运行总和