在模型之前可以使用KnockoutJS“with”绑定

时间:2014-01-28 19:41:33

标签: javascript knockout.js single-page-application

我有一个使用KnockoutJS的ASP.NET MVC4 SPA Web应用程序,这有点尴尬,因为据我所知,当页面最初在SPA中加载时,在AJAX调用检索它之前通常没有数据。当我尝试使用类似data-bind="with: myData"的属性绑定块内的所有类型的数据时,该节点内的整个DOM都会被清空,直到myData变为有效,这让我感到紧张,如果某些脚本可能依赖于这些元素可以附加脚本或其他东西。在加载过程中,页面的块消失并重新出现也很糟糕。所以我设计了一个with绑定的变体,如果值为空,它将阻止后代绑定,目前看起来像这样:

ko.bindingHandlers.safeWith = {
    'init': ko.bindingHandlers.with.init,
    'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        if ((value != undefined) && (value != null))
            ko.bindingHandlers.with.update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
    }
};

然后,我只需使用safeWith代替with,以确保在等待myData填充时我的DOM不会消失。

我的问题是:

  1. 这是使用淘汰赛的SPA的常见问题,如果是,通常如何处理?
  2. 我处理这个安全的方式还是冒着重复的事件/绑定被某种方式应用或者我不知道的风险?
  3. 我对网络学习关于淘汰赛和相关技术的漫游感到惊讶,我还没有遇到过这个问题。是否有充分的理由更喜欢让DOM的各个部分在他们被绑定的对象为空时消失;我试图保留它是否犯了错误?

2 个答案:

答案 0 :(得分:1)

我已经实现了一个自定义bindIf绑定处理程序,通过推迟绑定逻辑直到observable在其中有一个有效值来显着改善我们的结果:

ko.bindingHandlers.bindIf = {
    'init': function (element, valueAccessor) {
        return { 'controlsDescendantBindings': true };
    },
    'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        if (!$(element).data("bindIfPassed") && valueAccessor()) {
            $(element).data("bindIfPassed", true);
            ko.applyBindingsToDescendants(bindingContext, element);
        }
    }
}

应用于这样的高级节点:

<div data-bind="bindIf: myObservable()">

答案 1 :(得分:0)

我可以看到为什么你不希望带有绑定元素的DOM消失的原因,但它们很少。几乎所有这些都涉及需要特定时序的DOM操作。例如,在显示视图时将焦点设置为第一个输入字段。有时,这些问题的解决方法并不漂亮,在这种情况下,像你这样的绑定肯定会有很大的帮助。

一般来说,

  1. 我认为这是一个常见的问题。你提几个 问题:脚本依赖于这些元素的存在:in 一般来说,我会回答你的脚本是错误的。现在那是一个 有点刺耳,但我觉得你的代码味道有点像 如果没有某个DOM元素,脚本会崩溃 可用。其次,你觉得dom的部分消失了 再现不是一件好事。在这种情况下,也许你应该 '重置'你的observable绑定到别的东西 '空值'。创建通常所用对象的“空白”实例 进入observable,并使用而不是null,所以你的DOM 保持完整。如果这不是一个选项,那么您的方案不是 真的是一个用于绑定的用例(和你自己的绑定会 确实对这种情况有帮助。)
  2. 我不完全确定。我试图查看带绑定,但由于某种原因,我无法在Knockout代码中发现它。虽然它很容易测试,只需在with绑定中设置一个事件绑定,然后几次更改observable的值。看起来有点令人担心的是,当值未定义/为null时,你永远不会更新with-binding:我可以想象这很容易导致DOM下方的绑定错误。
  3. 这有很好的理由,特别是在单页应用程序中。我正在使用Knockout做一个非常庞大的应用程序作为SPA。通过正确使用with-binding并在卸载视图时清理我的viewmodel,我可以非常轻松地管理内存(其中DOM节点很重要),即使视图缓存在前端。如果我们没有相关数据不存在时卸载DOM节点的机制,应用程序运行速度会非常慢。这是我非常喜欢的数据驱动方法:显示的DOM部分是相关的部分,因为数据存在。