首页 文章

Knockoutjs计算了传递参数

提问于
浏览
42

我想知道在绑定时是否有可能使用knockoutjs来传递参数 .

我绑定了一个复选框列表,并希望绑定到我的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)" />

有什么建议?

4 回答

  • 2

    创建一个函数,其唯一目的是返回计算的observable . 它可以根据需要采用参数 . 如果你想要它是一个双向绑定,它必须是一个单独的计算observable .

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

    这是a fiddle,我使用这种技术来创建事件处理程序 . 你可以在这里做类似的事情 .

    您可以通过将函数作为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)"/>
    

    Demo


    但是,如果您只是尝试将所有这些复选框绑定到视图模型中的单个值,则无需执行此操作 . 在视图模型中对数组使用 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([])
    };
    

    Demo

  • 83

    接受的答案是不错的,但是如果你有一个为每个复选框生成一个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/

  • 6

    没有理由使用 computed 值 . 只需在View Model中定义一个函数,然后将 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());
    

    尽管如此,尝试尽可能多地将逻辑推入View模型是个好主意 . 建议创建一个View复制模型,将复选框建模为一个对象,然后关于是否应该选中复选框的逻辑可以封装在里面 .

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

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

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

相关问题