KnockoutJS 性能:仅呈现当前在视图中的元素(Clean/Destroy 其他)

KnockoutJS Performance: Only Render Elements that are Currently in View (Clean/Destroy Others)

我正在使用 KnockoutJS 开发一个应用程序,它打算在一个长的、可滚动的列表中显示 pages/slides。

这些页面中的每一个都具有一些高级的所见即所得功能以及大量其他工具和附加数据。

但是,随着 pages/slides 数量的增加,我注意到性能受到了巨大影响。

因此,我想更改为仅呈现视口中的 slides/pages 的方式。一旦你滚动经过一个项目,我希望 KnockoutJS 销毁它之前渲染的任何东西,而是渲染进入视口的任何东西。被销毁的项目应该用占位符 li-tag 替换(直到你滚动回到它们)。

目前有效的方法

到目前为止一切顺利,我整理了一个 JSFiddle,它很好地展示了如何只有 "visible" 项将其可观察的 "inView" 设置为 true。 查看向您展示视图模型如何响应滚动的演示:https://jsfiddle.net/1xxy6q83/

缺少什么

但是,问题是让条件显示正常工作。每当我尝试 mix/match foreachif 时,它就会停止工作。 我正在寻找的是 Knockout 只渲染在视口中看到的内容。当一个项目移出视图时,Knockout 应该清理它,删除所有事件,而是呈现一个非常简单的占位符 li-tag,以确保列表不会跳来跳去。

您可以使用 template 绑定,其中模板名称基于 inView 的值:

function Page(page) {
  var self = this;
  this.page = ko.observable(page);
  this.inView = ko.observable(false);
  this.templateName = function() {
    return self.inView() ? 'complex' : 'placeholder';
  };
}

绑定看起来像:

    <ul data-bind="foreach: pages">
      <li data-bind="inview: $data">
        <div data-bind="template: templateName()">

        </div>
      </li>
    </ul>

here's an updated fiddle。我在 inView 的设置上设置了时间延迟,这样您可以在滚动时看到 template-swapping 发生。