如何防止Knockout.js函数在页面加载时运行?

时间:2017-01-28 02:10:21

标签: javascript knockout.js

这是我正在使用的代码。控制台日志显示我正在调用onFilterChange方法两次(对于“select tags”中的每个函数定义一次。我猜我需要在data-bind中更改“event:{change:onFilterChange}”,但是我不熟悉Knockout.js,我们不支持ES6,所以不要使用“()=> onFilterChange”,这对我来说过去很有用:

function ProductionsView() {
    var self = this;

    self.showDateFilter = ko.observable(true);
    self.showCategoryFilter = ko.observable(true);
    self.showDateFilter = ko.observable(true);

    self.onFilterChange = function(data,event) {
        if (self.init()) {
            self.doFilter();
            console.log("onFilterChange was called. This is happening twice on page load before interacting with the filter. ");
        }
    };


    self.doFilter = function() {
        var df = self.selectedDateFilter();
        var cf = self.selectedCatFilter();

        if (typeof cf == 'undefined' || typeof df == 'undefined') {
            return;
        }
        // these are all defined as observables too, but not important since it's the "onFilterChange" that I don't want to call 
        self.amFiltering("All" !== df || "All" !== cf);
        self.allCatAndDate("All" === df && "All" === cf);
        self.offset(0);
        self.doAjaxSearchFiltered(true);
    };
}

var pv = new ProductionsView();
ko.applyBindings(pv);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div data-bind="visible: showDateFilterBar()">
  <select data-bind="
    value: selectedCatFilter,
    event: { change: onFilterChange },
    visible: showCategoryFilter()
  ">
    <option value="all">all</option>
    <option value="cat1">cat1</option>
  </select>
  <select data-bind="
    value: selectedDateFilter,
    event: { change: onFilterChange },
    visible: showDateFilter()
  ">
    <option value="all">all</option>
    <option value="date1">date1</option>
  </select>
</div>

2 个答案:

答案 0 :(得分:0)

我猜测当你的初始值传递给select元素时,applyBindings本身会触发更改事件。

您应该在模型中订阅observables本身的change事件,而不是在标记中订阅事件绑定。

self.selectedCatFilter.subscribe(onFilterChange);

self.selectedDateFilter.subscribe(onFilterChange);

答案 1 :(得分:0)

是的,你使用Knockout错了。 Knockout是关于自动值依赖性的,通常你不需要设置任何&#34;更改&#34;事件处理程序。

您设置了observable并订阅了它们。您将在更改时收到通知,例如,当用户更改了绑定的UI元素时,或依赖项之一发生更改时。

要订阅可观察的值,只需在computed.subscribe()内直接使用它们即可。两者都显示如下。运行代码示例以查看它的实际效果。

&#13;
&#13;
function ProductionsView() {
    var self = this;

    // values
    self.selectedDateFilter = ko.observable("all");
    self.selectedCatFilter = ko.observable("all");
  
    // computed values
    self.amFiltering = ko.computed(function () {
        return self.selectedDateFilter() !== "all" ||
               self.selectedCatFilter() !== "all";
    });
    self.allCatAndDate = ko.computed(function () {
        return self.selectedDateFilter() === "all" &&
               self.selectedCatFilter() === "all";
    });

    // subscriptions
    self.amFiltering.subscribe(function (value) {
        console.log("searching with filter=" + value);
        //self.doAjaxSearchFiltered(value);
    });
}

var pv = new ProductionsView();
ko.applyBindings(pv);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<select data-bind="value: selectedCatFilter">
  <option value="all">all</option>
  <option value="cat1">cat1</option>
</select>

<select data-bind="value: selectedDateFilter">
  <option value="all">all</option>
  <option value="date1">date1</option>
</select>

Viewmodel:
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
&#13;
&#13;
&#13;

您可以创建一个包含Ajax参数的计算值作为对象并订阅它,如下所示:

self.searchParams = ko.computed(function () {
    return {
        date: self.selectedDateFilter(),
        cat: self.selectedCatFilter()
    };
});

self.searchParams.subscribe(function (params) {
    return $.get("/your/url", params).done(function (data) {
        // populate your observables with new data
    });
});

这样就可以在任何相关更改时自动触发Ajax请求。