46

我想知道在绑定时是否可以使用 knockoutjs 传递参数。

我正在绑定一个复选框列表,并希望绑定到我的视图模型中的单个计算的 observable。在我的视图模型中(基于传递给读取函数的参数)我想根据某些条件返回真/假。

var myViewModel=function(){
    this.myprop=ko.computed({read: function(){
    //would like to receive an argument here to do my logic and return based on argument.
}
});
};

<input type="checkbox" data-bind="checked: myprop(someval1)" />
<input type="checkbox" data-bind="checked: myprop(someval2)" />
<input type="checkbox" data-bind="checked: myprop(someval3)" />

有什么建议么?

4

4 回答 4

89

创建一个函数,其唯一目的是返回一个计算的 observable。它可以根据需要接受参数。如果您希望它是双向绑定,它必须是一个单独的计算 observable。

然后在您的绑定中,使用适当的参数调用该函数。它返回的计算出的 observable 将绑定到您的视图中,并将照常更新。

这是我使用这种技术创建事件处理程序的小提琴。你可以在这里做类似的事情。

您可以通过使函数成为可观察对象上的方法来保持它的清洁。通过添加到ko.observable.fn原型或直接将其添加到可观察实例。

ko.observable.fn.bit = function (bit) {
    return ko.computed({
        read: function () {
            return !!(this() & bit);
        },
        write: function (checked) {
            if (checked)
                this(this() | bit);
            else
                this(this() & ~bit);
        }
    }, this);
};
// or
function ViewModel() {
    this.flags = ko.observable(0);

    this.flags.bit = function (bit) {
        return ko.computed({
            read: function () {
                return !!(this() & bit);
            },
            write: function (checked) {
                if (checked)
                    this(this() | bit);
                else
                    this(this() & ~bit);
            }
        }, this);
    }.bind(this.flags);
}    

然后应用于您的视图

<input type="checkbox" data-bind="checked: flags.bit(0x1)"/>
<input type="checkbox" data-bind="checked: flags.bit(0x2)"/>
<input type="checkbox" data-bind="checked: flags.bit(0x4)"/>
<input type="checkbox" data-bind="checked: flags.bit(0x8)"/>

演示


但是,如果您只是尝试将所有这些复选框绑定到视图模型中的单个值,则不需要这样做。checked在视图模型中的数组上使用绑定并为您的复选框指定一个值。每个检查的值都将添加到数组中。这将是一种双向绑定。

<input type="checkbox" data-bind="checked: checkedValues, value: 1"/>
<input type="checkbox" data-bind="checked: checkedValues, value: 2"/>
<input type="checkbox" data-bind="checked: checkedValues, value: 3"/>
<input type="checkbox" data-bind="checked: checkedValues, value: 4"/>
var viewModel = {
    checkedValues: ko.observableArray([])
};

演示

于 2012-11-04T06:29:22.150 回答
6

接受的答案是不错的,但是如果您有一个为每个复选框生成 ko.computed 的函数,那么您将使用多个匿名计算的 observables 添加不必要的开销,当您的复选框列表超过 4-5 个选项时,这些开销会迅速增加。

这是按位场景的更简单实现,但计算函数可以是任何需要的函数。

<input type="checkbox" data-bind="checked: checkedList, value: 1" />
<label>Value 1</label>
<input type="checkbox" data-bind="checked: checkedList, value: 2" />
<label>Value 2</label>
<input type="checkbox" data-bind="checked: checkedList, value: 4" />
<label>Value 4</label>
<input type="checkbox" data-bind="checked: checkedList, value: 8" />
<label>Value 8</label>

脚本:

var vm = function() {
    var vm = this;

    this.checkedList = ko.observableArray();
    this.bitwiseValue = ko.computed({
        read: function () {
            return vm.checkedList().reduce(function (prev, curr) {
                return prev | curr;
            }, 0);
        },
        write: function (myVal) {
            vm.checkedList.removeAll();
            var placeValue = 1;

            while(myVal > 0) {
                if((myVal % 2) == 1) {
                    alert(placeValue);
                    vm.checkedList.push(placeValue.toString());
                }

                myVal = myVal >>> 1;                    
                placeValue = placeValue * 2;
            }
        }
    }, this);
}

ko.applyBindings(vm);

此处的小提琴示例:http: //jsfiddle.net/i_vargas3/RYQgg/

于 2014-02-27T16:57:06.923 回答
3

没有理由使用computed值。只需在您的视图模型中定义一个函数并将其绑定checked到它。

下面是一个非常简单的例子。

--

HTML

<input type="checkbox" data-bind="checked: isEven(1)" />
<input type="checkbox" data-bind="checked: isEven(2)" />
<input type="checkbox" data-bind="checked: isEven(3)" />​

JS

var MyViewModel=function(){
    this.isEven = function(num) {
        return (num % 2) == 0;
    };
};
ko.applyBindings(new MyViewModel());

​--

话虽如此,尝试将尽可能多的逻辑推送到您的视图模型中是一个好主意。建议创建一个将您的复选框建模为对象的视图模型,然后可以将有关是否应选中复选框的逻辑封装在其中。

--

编辑:根据进行双向绑定的要求,我编写了一个扩展器来管理一个可观察的。

http://jsfiddle.net/jearles/j6zLW/5/

ko.extenders.bitwise = function(target, bitCount) { 
    target.bits = [];    
    target.checked = ko.observableArray();

    // Create bit array based on requested number of bits
    for (i=bitCount-1; i>=0; i--) {
        target.bits.push(''+Math.pow(2, i));
    }        

    // Define a function to create bits
    function makeBits(newValue) {
       var num = !isNaN(newValue) ? parseInt(newValue) : 0;
       var arr = [];
       for (i=0; i<target.bits.length; i++) {
          var bitValue = parseInt(target.bits[i]);
          if ((num & bitValue) == bitValue) arr.push(target.bits[i]);
       }
       target.checked(arr);
    }

    // Define a function to combine bits
    function makeBitwise(newBits) {
       var num = 0;
       for (i=0; i<target.bits.length; i++) {
         if (newBits.indexOf(target.bits[i]) > -1) num += parseInt(target.bits[i]);
       }
       target(num);
    }

    // Create initial bits
    makeBits(target());

    // Make bits whenever the value changes
    target.subscribe(makeBits);

    // Make number whenever the bits change
    target.checked.subscribe(makeBitwise);

    // Return the original observable
    return target;
};

var MyViewModel=function(){
    var self = this;
    this.number = ko.observable(2).extend({ bitwise: 8});

};
ko.applyBindings(new MyViewModel());​
于 2012-11-03T16:44:35.473 回答
0

在不了解细节的情况下,您似乎应该做的是定义一个 ko.observableArray 或计算数组值

HTML:

myprop: <input data-bind="value: myprop">
<div data-bind="foreach: selections">
  <label>
    <span data-bind="text: value"></span>
    <input type="checkbox" data-bind="checked: selected"/>
  </label>
</div>

JS:

  $(function() {
    function Model() {
        this.self = this
        self.myprop = ko.observable(14)
        self.bits = [1, 2, 4, 8, 16, 32, 64, 128]
        self.selections = ko.computed(function() {
            return self.bits.map(function(bit) {
                console.log(myprop() & bit)
                return {
                    value: bit,
                    selected: (myprop() & bit) == bit
                }
            })
        })
    }

    ko.applyBindings(new Model())
})

并且不从标记中传递值来定义模型状态

于 2012-11-03T16:32:11.553 回答