消除淘汰中引导程序开关状态变化的歧义

Disambiguating bootstrap-switch state changes in knockout

本文关键字:状态 变化 歧义 开关 引导程序 淘汰      更新时间:2023-12-22

我正在使用bootstrap开关和这个问题中引用的敲除绑定处理程序,如下所示:

ko.bindingHandlers.bootstrapSwitchOn = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
    $elem = $(element);
    $elem.bootstrapSwitch();
    // Set intial state
    $elem.bootstrapSwitch('setState', ko.utils.unwrapObservable(valueAccessor()));
    $elem.on('switch-change', function (e, data) {
        // Update the model when changed.
        valueAccessor()(data.value);
    }); 
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
    var vStatus = $(element).bootstrapSwitch('status');
    var vmStatus = ko.utils.unwrapObservable(valueAccessor());
    if (vStatus != vmStatus) {
        $(element).bootstrapSwitch('setState', vmStatus);
    }
}
};

这似乎运行得很好,我模拟了一把小提琴来说明我是如何在这里使用它的:

http://jsfiddle.net/swervo/of0q42j0/5/

然而,我有一些问题似乎无法以令人满意的方式解决:

1)如果我在ko.observable数组中有一个项目数组,我可以在所有项目上放置一个点击处理程序,并让它们调用父视图模型中的一个函数,如下所示:

data-bind="click: $parent.clickHandler"

当被调用时,它通过项自己的视图模型。这对于获取被点击项目的属性非常方便,例如id。我在上面放了一个按钮来说明这是多么容易做到

然而,如果我使用引导开关而不是简单的按钮,则开关似乎不知道它的父级,并且我找不到一种优雅的方式来将包含开关的视图模型传递到其父级,就像使用按钮一样。我试着给数组中的每个项一个对其父视图模型的引用,这确实有效,但创建了一个循环引用,因此似乎不是正确的方法。

2)在我正在构建的应用程序中,列表中项目的状态可以在不同的客户端上更改,并且本地状态需要更新以反映这些远程客户端。同样,状态也可以在本地客户端上更改,然后传播到其他客户端。我在这里的问题是如何在本地发生的状态更改(即,由于用户单击开关)和远程发生的更改(例如,由于来自服务器的更新)之间消除歧义。在我的实际项目中,我使用敲除订阅来监听链接到开关的值的变化,如下所示:

viewModel.observableValue.subscribe(function(newValue) {
    // test value on server and if it is different update
});

我希望避免从服务器接收更新,然后在交换机更改以反映新状态时再次更新服务器(使用相同的状态)。目前,我已经通过在发送更新之前测试服务器状态(如上面代码片段中所暗示的)来解决了这个问题,如果它与挂起的状态更新相同,我就会放弃它。(我已经使用上面引用的fiddle中的按钮模拟了服务器更新)。

我对这些问题的两个解决方案都感觉不到优雅,因此这里提出了这个问题。任何帮助都将不胜感激。

  1. 我不知道你说的"开关似乎不知道它的父母"是什么意思。正在查看http://knockoutjs.com/documentation/custom-bindings.html,我可以看到initupdate都有第五个参数bindingContext,如果您希望访问它,它具有父信息
  2. Ahem,我们过去做过的一个项目有一个切换按钮,它也遇到了同样的问题,这是一种非常简单的方法。对于本地生成的事件,只需将一个属性附加到对象,如.local = true;,并在更新中检查它(或在REST处理程序中附加它),以区分本地/与REST。不过,在更新中完成后,不要忘记从视图模型中删除该属性