如何在使用多个可观察函数时触发不同的ko.computed函数

时间:2012-10-11 04:05:03

标签: knockout.js

我正在尝试为一大块数字制作热图。 到目前为止,应该是相关地图一部分的数字应该由上下文指定

它起到了一定的作用..我仍然需要稍微研究一下rgb算法,但是有问题的部分是setHeat计算函数中的for循环。

我想要的是每当'max'或'min'改变时,我希望'elements'数组中当前的所有元素都更新它们的颜色。

但是当一个元素添加到'elements'数组时,我只想设置该元素的颜色,但这需要max和min,所以我不知道如何正确分离调用以便min和max更新将调用一个元素更新将调用另一个。

此外,我对如何提高我的约束力持批评态度。

<!-- ko foreach:items -->
            <tr>
                <td class="postCell">
                    <div class="ui-post-icon" data-bind="class: $parents[2].setPostIcon(post)"></div>
                    <span data-bind="text:post"></span>
                </td>
                <!-- ko foreach:combinations -->
                <td data-bind="heat:{value:amount,context:'exotics'}"></td>
                <!-- /ko -->
            </tr>
            <!-- /ko -->


ko.bindingHandlers.heat = {
        init: function (element, value, allBindings, viewModel, bindingConext) {
            var item = value();
            var model = bindingConext.$root;

            if (!model["koHeat"])
                model["koHeat"] = {};

            if (!model["koHeat"][item.context])
                model["koHeat"][item.context] = ko.observable(new HeatContext());

            var ctx = model["koHeat"][item.context];

            if (!isNaN(item.value)) {
                if (+item.value > ctx().max()) ctx().max(+item.value);
                if (+item.value < ctx().min()) ctx().min(+item.value);
                ctx().elements.push(element);
            }

            $(element).html(item.value).data('koHeat', item.value);

            //set value

            function HeatContext() {
                var self = this;
                this.max = ko.observable(0);
                this.min = ko.observable(Number.MAX_VALUE);
                this.elements = ko.observableArray([]);

                this.setHeat = ko.computed(function () {

                    var max = self.max(),
                        min = self.min(),
                        elems = self.elements(),
                        mid = (max + min) / 2,
                        range = max - min,
                        r, g, b, x;

                    for (var i = 0; i < elems.length; i++) {
                        var val = $(elems[i]).data('koHeat');
                        x = (val - mid) / range;
                        if (x > 0) {
                            g = Math.abs(Math.round(x* 100));
                            b = 0.0;
                            r = Math.abs(Math.round((1.0 - x) * 100));
                        } else {
                            g = Math.abs(Math.round(x * 100));
                            b = Math.abs(Math.round((1.0 - x) * 100));
                            r = 0.0;
                        }
                        log(r,g,b);

                        $(elems[i]).css('color', "rgb(" + r + "," + g + "," + b + ")");
                    }
                });
            }
        }
    };

修改 我为这种情况做了一个快速的小提琴

http://jsfiddle.net/rwJfK/3/

1 个答案:

答案 0 :(得分:1)

不要将setHeat设为computed,只需删除HeatContext前缀并订阅this.min即可将其声明为max内的私有函数{1}}更改如下:

this.min.subscribe(setHeat);
this.max.subscribe(setHeat);

现在,setHeat只会在minmax更新时运行 - 而不是在元素被推送到数组时运行。

有很多方法可以改善这种绑定。我会尝试在几天内整理一个改进版本。我会对这个答案进行编辑。