knockout.js cleanNode是否会删除所有关联的事件侦听器?

时间:2017-04-18 20:57:59

标签: javascript knockout.js

我通过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();
        }
    });
}

还有更好的方法吗?清理节点是否会删除所有关联的事件侦听器?

1 个答案:

答案 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>