1

我将bootstrap-switch与从这个问题中引用的敲除绑定处理程序一起使用,如下所示:

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

当我的开关更改以反映新状态时,我想避免从服务器接收更新然后再次更新服务器(具有相同的状态)。目前,我通过在发送更新之前测试服务器状态(如上面的代码片段中所暗示的那样)来解决此问题,如果它与挂起状态更新相同,我将丢弃它。(我已经使用上面引用的小提琴中的按钮模拟了服务器更新)。

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

4

1 回答 1

0
  1. 我不确定您所说的“交换机似乎不知道它的父母”是什么意思。查看http://knockoutjs.com/documentation/custom-bindings.html,我可以看到init两者update都有第 5 个参数,bindingContext如果您希望访问它,它具有父信息。
  2. 咳咳,我们过去参与的一个项目有一个切换按钮,它遇到了同样的问题,并且修复是一种非常简单的方法。对于本地生成的事件,只需将属性附加到对象,例如.local = true;并在更新中检查它(或将其附加到 REST 处理程序中)以区分本地/与 REST。不要忘记在更新完成后从视图模型中删除该属性。
于 2015-02-17T17:25:38.687 回答