我有自定义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的情况?如果是这样,为什么?
答案 0 :(得分:4)
您正在使用jQuery替换DOM树的一部分。 Knockout无法知道哪些元素被删除,也无法在绑定模型上调用dispose
。
在致电html
之前,使用淘汰赛ko.cleanNode(element)
绑定添加/删除新部分或(不推荐)致电$el.html
。
示例显示:
dispose
foreach
,if
,with
),敲门 时会调用dispose
必须删除ko.cleanNode
时,knockout会从模型中分离所有节点,调用dispose
,然后让您使用剩余的DOM节点执行所需的操作。
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;