我通过ajax加载页面,在每个ajax请求开始时我清理页面然后在添加的新页面上加载applybindings。我始终保持一个持久的模型,它是更新的视图。
addEventListeners(){
this.subscriptions.push(PubSub.subscribe('route.start', this.removeShopView));
this.subscriptions.push(PubSub.subscribe('route.success', this.addShopView));
}
removeShopView(){
ko.cleanNode(this.currentPage);
}
addShopView(){
this.currentPage = document.querySelector('.page-context');
ko.applyBindings(this.model, this.currentPage);
}
我的问题是在清理节点时,我似乎正在擦除附加到页面上的锚链接的事件监听器。此锚链接包含一个元素,在我的模型中显示产品的计数器
<ul>
<li><a class='nav-bag' href="/bag">Bag<span data-bind='text: counter'></span></a></li>
</ul>
我在别处设置的此事件不再被触发,我的页面刷新而不是运行ajax调用。
setupLinks(){
this.pageContextWrap.addEventListener("click", (e) => {
this.linkClickType = undefined;
if (e.target && e.target.nodeName.toLowerCase() == 'a') {
if(href.indexOf(document.domain) === -1) {
console.log("outside link");
this.href = false;
return;
}
// anchor link is local page, ajax load the href
this.doAjaxCall();
e.preventDefault();
e.stopPropagation();
}
});
}
还有更好的方法吗?清理节点是否会删除所有关联的事件侦听器?
答案 0 :(得分:3)
首先,如您所见,you should not use cleanNode
。
其次,你应该更喜欢让Knockout管理整个DOM而不是一大块。在您的情况下,您正在使用老式的操纵DOM自己的方式处理应用程序,并使用Knockout管理不断变化的内容。
您真正需要的是html binding的一个版本,它将绑定应用于其内容。使用applyBindingsToDescendants
的简单自定义绑定处理程序可以使其工作。例如:
ko.bindingHandlers.boundHtml = {
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
const contentHtml = ko.unwrap(valueAccessor());
element.innerHTML = contentHtml;
ko.applyBindingsToDescendants(bindingContext, element)
}
};
const someContents = [
'First content <span data-bind="text:someValue"></span>',
'Second content <span data-bind="text:anotherValue"></span>',
'Third content <span data-bind="text:someValue() + anotherValue()"></span>'
]
ko.applyBindings({
pageContent: ko.observable('hi there'),
someValue: ko.observable(3),
anotherValue: ko.observable('foo'),
changePage() {
if (someContents.length) {
this.pageContent(someContents.shift());
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="boundHtml:pageContent"></div>
<button data-bind="click:changePage">Change</button>