【问题标题】:How to prevent Knockout.js function from running on page load?如何防止 Knockout.js 函数在页面加载时运行?
【发布时间】:2017-06-13 19:51:18
【问题描述】:

这是我正在使用的代码。控制台日志显示 onFilterChange 方法被调用了两次(对于“选择标签”中的每个函数定义一次)。我猜我需要在数据绑定中更改“事件:{ 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>

【问题讨论】:

  • 什么是 selectedCatFilter 和 selectedDateFilter,可观察的还是计算的?你能显示这些代码吗?
  • 如果您不希望它在页面加载时运行,您希望它何时运行?您能否等到该事件发生后再致电applyBindings(),然后使用该事件触发呼叫?
  • @JasonSpake 抱歉,我在其中添加了那些可观察的声明。@coralv 是使用applyBindings() 的好文档:stackoverflow.com/questions/18990244/… 我只希望在选择哪个过滤器时调用该方法onchange一想。我要加applyBindings(self, document.getElementById("date-results") )吗?

标签: javascript knockout.js


【解决方案1】:

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

您应该订阅模型中可观察对象本身的更改事件,而不是标记中的事件绑定。

self.selectedCatFilter.subscribe(onFilterChange);

self.selectedDateFilter.subscribe(onFilterChange);

【讨论】:

    【解决方案2】:

    是的,您使用的 Knockout 错误。 Knockout 完全是关于自动值依赖,通常您根本不需要设置任何“更改”事件处理程序。

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

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

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

    您可以创建一个包含 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 请求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-09
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 2020-01-01
      • 2015-03-12
      • 2021-06-02
      • 1970-01-01
      相关资源
      最近更新 更多