Knockoutjs计算传递参数

我想知道是否有可能与knockoutjs绑定时传递参数。

我绑定了一个checkbox的列表,并希望绑定到我的viewmodel中的一个计算的observable。 在我的viewmodel(根据传递给read函数的参数),我想根据一定的条件返回true / false。

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)" /> 

有什么build议么?

创build一个函数,其唯一目的是返回一个计算的observable。 它可能需要参数。 如果你希望它是一个双向绑定,它将必须是一个单独的计算观察值。

然后在你的绑定中,用适当的参数调用该函数。 它返回的计算的观察值将被绑定到你的视图中,并且将照常更新。

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

你可以通过在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)"/> 

演示


但是,如果您只是试图将所有这些checkbox绑定到视图模型中的单个值,则不需要这样做。 在你的视图模型的数组中使用checked绑定,并给你的checkbox一个值。 每个选中的值将被添加到数组中。 这将是一个双向的约束力。

 <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([]) }; 

演示

接受的答案是体面的,但如果你有一个函数为每个checkbox生成一个ko.computed,那么你将增加不必要的开销和多个匿名计算的观察值,当你的checkbox列表超过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/

没有理由使用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()); 

尽pipe如此,尝试尽可能多地将逻辑推入视图模型是个好主意。 build议创build一个视图模型,将您的checkboxbuild模为一个对象,然后closurescheckbox的逻辑可以封装在内部。

编辑:基于要做双向绑定的要求,我写了一个扩展器来pipe理一个observable。

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());​ 

不知道具体情况,似乎你应该做的是定义一个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()) }) 

而不是从标记中传递值来定义模型状态

Interesting Posts