Knockout组件部署不称为

时间:2018-01-29 12:52:14

标签: javascript html knockout.js knockout-3.0

我有自定义KO组件地址输入

ko.components.register('address-input', {
    viewModel: { createViewModel: function ({}, componentInfo) {
        var self = {};
        self.dispose = function() {
            // When removed by KO, dispose computeds and subscriptions
        };

        return self;
    }},
    template: 'address-input'
});

相应的模板是 address-input.html

<div  class`enter code here`="clearfix row">
    <!-- elements come here -->
</div>

我的应用程序是SPA,其基本布局如下所示

main.html 将包含 section.html ,其中包含地址输入,html 。在页面导航中, section.html 将被其他html替换,依此类推。

htmls部分是通过AJAX加载的

        $j.ajax({
            url: url,
            success: function(htmlText) {
                var $el = $j(element);
                $el.html(htmlText);
                ko.applyBindingsToDescendants(bindingContext, $el[0]);
            },
            cache: false,
            mimeType: 'text/html-ko'
        });

我将来可能会在地址输入组件中订阅一些observable。当发生这种情况时,我希望在离开页面时调用dispose方法。但现在还没有发生。这有什么不对?这是不是从内存中删除DOM的情况?如果是这样,为什么?

1 个答案:

答案 0 :(得分:4)

您正在使用jQuery替换DOM树的一部分。 Knockout无法知道哪些元素被删除,也无法在绑定模型上调用dispose

在致电html之前,使用淘汰赛ko.cleanNode(element)绑定添加/删除新部分或(不推荐)致电$el.html

示例显示:

  • 当您从DOM手动删除组件时,没有通知淘汰赛并且无法拨打dispose
  • 当你使用常规绑定来改变DOM时(例如foreachifwith),敲门 时会调用dispose必须删除
  • 当您致电ko.cleanNode时,knockout会从模型中分离所有节点,调用dispose,然后让您使用剩余的DOM节点执行所需的操作。

&#13;
&#13;
ko.components.register('mycomponent', {
    viewModel: function(params) {
      this.dispose = () => console.log("Dispose called");
    },
    template: "<li>My Component</li>"
});
 
// Some example data to render a list
const comps = ko.observableArray([1, 2, 3, 4]);

// Remove straigt from the DOM without knockout...
const badRemove = () => document
  .querySelector("mycomponent:last-child")
  .remove();
 
const manualDetach = () => ko.cleanNode(document.querySelector("div"));
  
// Use knockout to alter the DOM
const goodRemove = () => comps.shift();

ko.applyBindings({ comps, badRemove, goodRemove, manualDetach });
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind="foreach: comps">
  <mycomponent></mycomponent>
</div>

<button data-bind="click: badRemove">bad remove</button>
<button data-bind="click: goodRemove">good remove</button>
<button data-bind="click: manualDetach">clean node</button>
&#13;
&#13;
&#13;