在Knockout JS中保存对DOM元素引用的正确模式

Correct pattern to hold a reference to a DOM element in Knockout JS

本文关键字:引用 模式 元素 DOM JS Knockout 保存      更新时间:2023-09-26

我知道在Knockout模型中处理DOM是一种不好的做法。但是,保存对模型中元素的引用的正确模式是什么呢?

假设我有一个菜单模型:

MenuModel = function()
{
    var self = this;
    self.buttons = [{ text: "set color" }, { text: "set border" }];
};

现在,这个菜单表示一个DOM元素,菜单中的每个按钮都操作所表示元素的DOM。

这是存储元素引用的正确模式吗?

MenuModel = function(el)
{
    var self = this;
    self.element = el;
    self.buttons = [{ text: "set color" }, { text: "set border" }];
};

因此,当单击菜单按钮时,该按钮的父模型(MenuModel)保存对元素的引用。

我理解解决方案是为所表示的元素提供一个Knockout模型,并更改该模型,以便元素根据模型更改而更改。但这对我来说是不实际的,在这一点上,我真的需要直接改变元素DOM。

为什么要在JS中保存DOM元素的引用?我认为这是一种反模式。看看这张来自维基百科的MVVM图表。显然你的MenuModel不是一个真正的模型,而是一个viewModel;它不包含任何数据,只包含表示逻辑。模型将是您从后端获得的JSON/XML数据,并最终通过构造函数转换为命名对象实例。viewModel (JS)和view (HTML)之间的流通过data-binding绑定。如果您坚持使用Knockout提倡的模式,则应该保持如下的简单:

<ul data-bind="foreach: buttons">
  <li data-bind="text: text"></li>
</ul>

您可以简单地向每个按钮对象添加一个action属性,并传递参数yourFunction(data, e)来操作您的视图,如下面的代码片段所示。如果您需要访问视图层次结构中的其他元素,您可以始终为其添加一个类/id,然后使用ko.dataFor(elem)ko.contextFor(elem)引用其数据。

<ul data-bind="foreach: buttons">
  <li data-bind="text: text, click: action"></li>
</ul>

为了性能和代码的可读性,您可能不希望将事件绑定附加到每个元素(特别是在列表中)。在这种情况下,请参考Knockout的低调事件处理部分或其他解决方案,如R.Niemeyer的插件Knockout委托事件。

所以要回答But what would be the correct pattern to hold a reference to an element in a model? -我会说,没有。在我所编写的所有Knockout代码中,我想不出有哪一种情况需要这样做。如果这还不能让人信服,那就读一读什么是关注点分离?