Knockout JS 将视图模型绑定到多个分布式元素 ID

Knockout JS bind view model to multiple distributed element IDs

这与我的问题类似,但解决方案似乎是创建一个靠近的公共父级。就通用性而言,我能做到的唯一方法是绑定到 document 或类似的东西,但它违背了目的:

Can I applyBindings to more than one DOM element using Knockout?

是否推荐像这样将单个视图模型实例绑定到多个ID。我试过了,它适用于简单的情况:

ko.applyBindings(newVm, document.getElementById('grapes'));
ko.applyBindings(newVm, document.getElementById('apples'));

我这样做的原因是我想使用内置功能绑定到单个页面应用程序上的特定元素,但这些元素没有共同的父元素。

应用绑定时,是否会创建视图模型实例的任何副本,这会导致它占用大量内存?

这与单个页面视图的多个视图模型无关,也与同一元素的多个视图模型无关。一个示例用例是 serverConnection 视图模型,其中连接和断开按钮位于工具栏的顶部,而连接状态位于状态栏的底部。

Is it recommended to bind a single view model instance to multiple IDs

不,不推荐。但也不一定是错的...

推荐的方法是使用 with 绑定。例如:

JS

const serverConnection = new ServerConnection();
const app = new App();

ko.applyBindings({ app, serverConnection });

HTML

<body>
  <header data-bind="with: serverConnection">
    <button data-bind="click: connect">Connect</button>
    <button data-bind="click: disconnect">Disconnect</button>
  </header>

  <article data-bind="with: app">
    ...
  </article>

  <footer data-bind="with: serverConnection">
    <div data-bind="text: statusCode"></div>
  </footer>
</body>

可运行代码段

const serverConnection = new ServerConnection();
const app = new App(serverConnection);

ko.applyBindings({ app, serverConnection });


function App(connection) {
  this.user = connection.user;
  
  this.heading = ko.pureComputed(
    () => this.user() ? `Welcome, ${this.user()}` : `Connect to get started...`
  );
}

function ServerConnection() {
  this.connected = ko.observable(false);
  this.connecting = ko.observable(false);
  this.user = ko.observable(null);
  
  this.connect = () => {
    this.connecting(true);
    setTimeout(
      () => {
        this.connected(true);
        this.user("Jane Doe");
        this.connecting(false);
      },
      1500
    )
  };
  
  this.disconnect = () => {
    this.user(null);
    this.connected(false);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<header data-bind="with: serverConnection">
  <button data-bind="click: connect, disable: connecting">Connect</button>
  <button data-bind="click: disconnect, disable: connecting">Disconnect</button>
</header>

<article data-bind="with: app">
  <h2 data-bind="text: heading"></h2>
</article>

<footer data-bind="with: serverConnection">
  <div data-bind="text: connected() ? '✅' : ''"></div>
</footer>