【问题标题】:How to track state change for multiple checkboxes in ko.js如何在 ko.js 中跟踪多个复选框的状态变化
【发布时间】:2020-12-23 17:49:27
【问题描述】:

这里是小提琴:https:https://jsfiddle.net/t5v7fmoq/1/

我想要达到的目标:

我希望能够根据收到的状态变量(可以有真值或假值)自动更新复选框视图

三个复选框的状态变量(带有初始状态)是:

  self.state1 = ko.observable(true);
  self.state2 = ko.observable(false);
  self.state3 = ko.observable(true);

在初始化函数中我填充 observablearray:

  self.init = function() {
    self.availableItems([
      new Item(1, "item1", self.state1(), self.onItemStateChange),
      new Item(2, "item2", self.state2(), self.onItemStateChange),
      new Item(3, "item3", self.state3(), self.onItemStateChange)
    ]);

在 Item 函数中,我设置了 observable 属性和 onChnage 方法:

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);
  });
}

使用 setTimeout 我伪造了一个一次性的 ajax 调用,它设置了新的状态:

setTimeout(()=>{
self.state1(false)
self.state2(true)
self.state3(false)
self.availableItems()[0].state(self.state1())
self.availableItems()[1].state(self.state2())
self.availableItems()[2].state(self.state3())
},1000)

但是,我想要实现的是,我想避免输入以下内容:

self.availableItems()[0].state(self.state1())
self.availableItems()[1].state(self.state2())
self.availableItems()[2].state(self.state3())

我想使用常见做法和最佳编码来编写此行为并跟踪此状态... 我不知道如何以不同的方式解决这个问题。

我尝试使用这样的数组(以便稍后我可以使用 forach 和索引):

setTimeout(()=>{
self.state1(false)
self.state2(true)
self.state3(false)
self.availableItems()[0].state(self.itemStatus()[0])
self.availableItems()[1].state(self.itemStatus()[1])
self.availableItems()[2].state(self.itemStatus()[2])
},1000)

但这并没有按预期工作。

简而言之,我想了解对行为进行编码的编码方法,以便在从服务器接收到新状态时,将正确的状态应用于正确的复选框,并正确更新正确的复选框视图。

【问题讨论】:

  • 您的复选框值基于Item.state 显示。为什么需要ViewModel 中的state1state2itemStatus 属性?您始终可以使用 availableItems 访问它们,就像在 activeItemss 中所做的那样。
  • 如何从服务器保存和获取数据?它基于id 字段?
  • 因为 state1、state2 和 state3,我在真实代码中模拟一种情况,我从服务器接收数据,使用 ko.js mapp 插件映射
  • 但是,为什么需要多个连续编号的状态属性?复选框状态在 Item 对象内。为什么需要ViewModel 中的重复信息。当发生变化时,您需要更新这两个地方。即使您从服务器获取数据,您也有id 参数来确定要更新哪个复选框?
  • 这是因为我无法控制来自服务器端的内容。在这种情况下我将如何编码?你有什么建议?

标签: javascript arrays mvvm knockout.js observable


【解决方案1】:

一般事实:如果您创建编号变量(item1item2item3),那么您做错了什么。使用数组。

根据如何您从服务器获取状态更新,updateState 的实现需要更改。我下面的实现假设你得到一个布尔值数组,例如[true, true, false].

让视图模型接受params 对象并用它初始化自己是个好主意,下面的代码就是这样做的。

function Item(params) {
    var self = this;

    self.id = ko.observable(params.id);
    self.name = ko.observable(params.name);
    self.state = ko.observable(params.state);
}

function ItemList(params) {
    var self = this;

    self.items = ko.observableArray(params.items.map(item => new Item(item)));

    self.updateState = function () {
        var items = self.items(),
            randomStates = items.map(item => Math.random() < 0.5);

        randomStates.forEach((state, i) => items[i].state(state));
    };
}


var viewModel = new ItemList({
    items: [
        {id: "item1", name: "Item 1", state: false},
        {id: "item2", name: "Item 2", state: false},
        {id: "item3", name: "Item 3", state: true},
    ]
});

ko.applyBindings(viewModel);
.switchName {
  font-weight: bold;
}
pre {
  position: absolute;
  right: 0;
  top: 0;
  left: 50%;
  font-size: smaller;
]
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind="foreach: items">
  <div class="switchBox">
    <input type="checkbox" data-bind="checked: state, attr: {id: id}">
    <label class="switchName" data-bind="text: name, attr: {for: id}"></label>
  </div>
</div>
<button data-bind="click: updateState">Simulate Random Update</button>

<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

【讨论】:

  • 非常感谢您的精彩解释。但是我无法将其标记为已回答,因为我仍然不知道如何解决此问题,因为您的假设是我从服务器返回数组,但它不是数组,我从返回 state1、state2 和 state3服务器。您能否解释一下如何针对这种情况修改此代码?
  • @johndoe 如何你拿回来了?作为一个对象?它到底长什么样子?
  • 这是准确的调用:BaseViewModel.call(this, { "state1": 1, "state2": 1, "state3": 0, }, baseEndpoint + '/status');在 BaseViewModel 我有这个: function BaseViewModel(defaults, remoteUrl, mappings) { if (mappings === undefined) { mappings = {}; } 变量自我 = 这个; self.remoteUrl = remoteUrl; // 可观察的属性 ko.mapping.fromJS(defaults, mappings, self); self.fetching = ko.observable(false); }
  • @johndoe 不要将代码发布到 cmets。将其添加到您的问题中,这样更容易阅读。
  • @johndoe ...当您使用它时,请像我在回答中所做的那样制作一个功能代码示例,其中包含 Knockout.js 和映射插件以及带有绑定的 HTML 视图,所以有一个“运行代码 sn-p”按钮来演示该问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多