knockout.js 敲除和applyBindings -如何控制范围?

xfb7svmp  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(172)

我是knockout的新手,所以会提出很多问题。但我对数据绑定并不陌生。所以我在我的期望和现实之间的差异上敲我的头。下面是一个关于applyBindings的非常基本的问题。
看起来applyBindings有参数“view model”,对我来说,它是域对象图(作为javascript对象),加上可能是为了创建视图而添加的额外的帮助器。但我一开始完全忽略的是绑定的范围!我希望它应用于当前的父DOM元素。但不是,它是全局应用于整个页面的!
那么,在一个HTML文档中只能有一个视图模型的期望是什么呢?这对我来说是非常令人惊讶的!我该如何创建一个单页面的Web应用程序,其中一个面板显示地址簿,另一个面板显示我的约会,另一个面板显示一个要审查的贷款申请,还有一个面板显示另一个贷款的承保?它们都是完全不同的东西。我真的应该把它们都链接到一个单一的视图模型中吗?
在我的预期中,您将一个javascript对象绑定到一个DOM元素,其中的所有内容都会呈现它。对于每个新的嵌套DOM元素,焦点对象可能会发生变化。它可能会从父对象的某个foreach绑定中流出。但是,两个兄弟对象DOM元素可能并排放置并且具有完全不同的视图模型,还有一个不同的生命周期。比如当我在我的承保工作流程中时,我需要快速打开一个地址簿或我的日历。所有这些都在一个单页应用程序中。不同的不相关DOM元素所使用的不同视图模型之间不应该有全局干扰。
然而,在这里,我们使用了knockout,我看到它只有一个ko.applyBindings(viewModelObject)用于整个页面。
我遗漏了什么?是什么阻止我们修改ko.applyBindings以接受两个参数,视图模型对象和DOM元素来显示它?我可以尝试这样做,但我担心如果敲除是在这种全局思维模式下设计的,那么在同一页面上多次运行敲除机制可能会有很多问题?

hgqdbh6s

hgqdbh6s1#

  • 我很抱歉,如果我的答案已经让人失望了。但是因为我有一个非常紧急的项目,我需要尽快解决我的问题,我正在阅读淘汰赛的源代码,它是相当好的组织和使用良好的名称,所以它是相当容易理解的;因此我自己找到了答案。*

答案是,是的,您可以将绑定应用于您选择的父元素。document.body仅在您不输入任何内容的情况下才是默认的。
因此,从现在开始,我将(告诉我的团队)总是使用为rootNode指定的第二个参数来调用applyBindings。

<div>
  ... all my UI elements for this thing ...
  ... then last element in this div:
  <script type="text/javascript">ko.applyBindings(viewModelObject, document.currentScript.parentElement);</script>
</div>

这样,我就可以有多个视图模型,每个视图模型都有自己DOM元素。
另外,我还想知道,knockout是否不以某种方式将模型对象分配给DOM元素?我也可以在我的script标记中这样做:

<div>
  ... all my UI elements for this thing ...
  ... then last element in this div:
  <script type="text/javascript">
     const viewElement = document.currentScript.parentElement;
     viewElement.viewModelObject = viewModelObject;
     ko.applyBindings(viewModelObject, viewElement);
  </script>
</div>

并且这允许我在DOM元素上找到当前视图模型对象(如果只是为了调试的话),DOM元素是视图的根。(如果所有其他后代绑定也能这样做就好了,但这可能是另一个问题的主题。)
实际上,我决定在我们的常规配置中放置一个ko.applyBindings函数的硬替换:

ko._applyBindings = ko.applyBindings;
ko.applyBindings(viewModelObject, rootNode, extendContextCallback) {
    rootNode = rootNode || document.currentScript.parentElement;
    rootNode.viewModelObject = viewModelObject;
    ko._applyBindings(viewModelObject, rootNode, extendContextCallback);
}

现在,我甚至不必说服我团队这样做,他们会自动地这样做,甚至在没有意识到这一点的情况下。

相关问题