【问题标题】:Complex nested nested if/else in the view causing performance issues视图中复杂的嵌套 if/else 导致性能问题
【发布时间】:2019-11-15 17:35:35
【问题描述】:

我在 foreach 的视图中嵌套了 if/else 绑定,大约需要一秒钟的时间来处理。它在创建 Dom 时阻止渲染。我计划在 JavaScript 中执行 if/else 条件并将整个 dom 元素发送到预先准备好的视图以加快速度。但是我是淘汰赛的新手,所以不确定这是否是一种有效的方法或者是否有更好的选择。下面的代码是有问题的代码,其中大部分数据被剥离以显示结构。在单个 a、li 等内部是对 DOM 元素的单个绑定。

<ul data-bind="foreach: categories; ">
<!-- ko if: $data.childCategories -->

<!-- ko ifnot: $data.id == 'example' -->

<!-- ko if: $data.id == 'another-example' -->

<li data-bind="attr: {'data-children': childCategories}">
    <!-- ko if: $data.id.indexOf('link-') < 0 -->
        <!-- ko if: $data.childCategories -->
            <a>

            </a>
        <!-- /ko -->
        <!-- ko ifnot: $data.childCategories -->
            <a>

            </a>
        <!-- /ko -->
    <!-- /ko -->

    <!-- ko if: $data.id.indexOf('link-') >= 0 -->
        <!-- ko if: $data.longDescription.indexOf('http') >= 0 -->
            <!-- ko if: $data.childCategories -->
                <a></a>
            <!-- /ko -->
            <!-- ko ifnot: $data.childCategories -->
                <a></a>
            <!-- /ko -->
        <!-- /ko -->
        <!-- ko ifnot: $data.longDescription.indexOf('http') >= 0  -->
            <!-- ko if: $data.childCategories -->
                <a></a>
            <!-- /ko -->
            <!-- ko ifnot: $data.childCategories -->
                <a></a>
            <!-- /ko -->
        <!-- /ko -->
    <!-- /ko -->


    <ul data-bind="foreach: childCategories ">
        <li>
            <!-- ko if: $data.id.indexOf('link-') < 0 -->
                <a></a>
            <!-- /ko -->

            <!-- ko if: $data.id.indexOf('link-') >= 0 -->
                <!-- ko if: $data.longDescription.indexOf('http') >= 0 -->
                    <!-- ko if: $data.childCategories -->
                        <a></a>
                    <!-- /ko -->
                    <!-- ko ifnot: $data.childCategories -->
                        <a></a>
                    <!-- /ko -->
                <!-- /ko -->
                <!-- ko ifnot: $data.longDescription.indexOf('http') >= 0  -->
                    <!-- ko if: $data.childCategories -->
                        <a></a>
                    <!-- /ko -->
                    <!-- ko ifnot: $data.childCategories -->
                        <a></a>
                    <!-- /ko -->
                <!-- /ko -->
            <!-- /ko -->


            <!-- ko if: $data.childCategories -->
                <div>
                    <div>
                        <div>
                            <!-- ko if: $data.id.indexOf('link-') < 0 -->
                                <a></a>
                            <!-- /ko -->
                            <!-- ko if: $data.id.indexOf('link-') >= 0 -->
                                <!-- ko if: $data.longDescription.indexOf('http') >= 0 -->
                                    <a></a>
                                <!-- /ko -->
                                <!-- ko ifnot: $data.longDescription.indexOf('http') >= 0  -->
                                    <a></a>
                                <!-- /ko -->
                            <!-- /ko -->
                        </div>
                        <ul data-bind="foreach: $data.childCategories">
                            <li></li>
                        </ul>
                    </div>
                </div>
            <!-- /ko -->
        </li>
    </ul>
</li>
<!-- /ko -->

<!-- ko ifnot: $data.id == 'another-example' -->
<li data-bind="attr: {'data-children': childCategories}">
        <!-- ko if: $data.id.indexOf('link-') < 0 -->
            <!-- ko if: $data.childCategories -->
                <a>

                </a>
            <!-- /ko -->
            <!-- ko ifnot: $data.childCategories -->
                <a>

                </a>
            <!-- /ko -->
        <!-- /ko -->

        <!-- ko if: $data.id.indexOf('link-') >= 0 -->
            <!-- ko if: $data.longDescription.indexOf('http') >= 0 -->
                <!-- ko if: $data.childCategories -->
                    <a></a>
                <!-- /ko -->
                <!-- ko ifnot: $data.childCategories -->
                    <a></a>
                <!-- /ko -->
            <!-- /ko -->
            <!-- ko ifnot: $data.longDescription.indexOf('http') >= 0  -->
                <!-- ko if: $data.childCategories -->
                    <a></a>
                <!-- /ko -->
                <!-- ko ifnot: $data.childCategories -->
                    <a></a>
                <!-- /ko -->
            <!-- /ko -->
        <!-- /ko -->




            <!-- ko if: $data.childCategories -->
            <div>
                    <div>
                        <div>
                            <!-- ko if: $data.id.indexOf('link-') < 0 -->
                                <a></a>
                            <!-- /ko -->
                            <!-- ko if: $data.id.indexOf('link-') >= 0 -->
                                <!-- ko if: $data.longDescription.indexOf('http') >= 0 -->
                                    <a></a>
                                <!-- /ko -->
                                <!-- ko ifnot: $data.longDescription.indexOf('http') >= 0  -->
                                    <a></a>
                                <!-- /ko -->
                            <!-- /ko -->
                        </div>
                        <ul data-bind="foreach: $data.childCategories">
                            <li></li>
                        </ul>
                    </div>
                </div>
            <!-- /ko -->









    </li>
<!-- /ko -->


<!-- /ko -->




<!-- /ko -->


<!-- ko ifnot: $data.childCategories -->

    <!-- ko if: $data.id.indexOf('link-') < 0 -->
        <li>
            <a>
            </a>
        </li>
    <!-- /ko -->
    <!-- ko if: $data.id.indexOf('link-') >= 0 -->
        <li></li>
    <!-- /ko -->
<!-- /ko -->

【问题讨论】:

  • 您当前的视图是什么样的?可能有更好的方法,但我们需要先看看你有什么。
  • 我无法发布代码,但我可以更详细地了解它的构造方式。我们检索一个 JSON 对象,该对象包含其他对象的数组,这些对象又具有更多嵌套数组,深度为几层。这定义了产品目录类别的结构。现在构造的视图在顶层对象上有一个 foreach 和多个级别的 if/else 和数据绑定。渲染块,您可以看到多个布局/绘画正在发生。
  • 如果这没有帮助,我可以在这里发布一个精简版来帮助说明问题。
  • 我添加了结构的精简版。

标签: knockout.js


【解决方案1】:

您是否尝试过在 observableArray() 上添加延迟更新扩展?这样,这一切都是异步发生的,主要是在任何 ui(重新)绘制之前

this.data = ko.observableArray().extend({ deferred: true });

查看更多信息:https://knockoutjs.com/documentation/deferred-updates.html

另外,当您准备数据时还有另一个小技巧,如果您已经在处理 observableArray() 并在更新绑定的 child-observables 等时进行迭代,有很多来回的通知,那就是有时使用简单的 js 对象更容易,然后像这样将所有更改立即推回可观察对象

var items = ko.observableArray();
//do something with the items here
items.push.apply(items, [1, 2, 3, 4]);

这样做可能会帮助您将 if-then-else 检查设置为数组中每个项目的布尔值,在 ui 渲染将其排序并移入代码时提升检查.. 只是一条建议。 无论哪种方式,淘汰赛都应该能够处理 - 很多 - if then else 条件而不在 ui 中查看太多问题,大多数情况下,您可以通过重新考虑如何使用 observables 来加快处理速度。

我从事的控件包含来自 api 和 observableArray 的 20k+ 项,过滤出条件子集,并在几毫秒内将它们显示到网页上,并带有模板和 if-then 条件。 (是的,我知道正确使用它有点多,但这不是重点)

【讨论】:

  • 谢谢我昨天尝试了延迟,但对我来说没有明显的改善。我会试试你建议的替代方法。
  • 如果它对您没有帮助,您应该真正尝试为您想要实现的目标添加一个非常基本的 jsfiddle,如果不查看您的内容,我们可能无法完全了解其他内容'实际上在做。
  • 当然可以。今天下午我会整理一些东西。
  • 我添加了结构的精简版。
  • 我很抱歉,但我个人想要一个显示 1 秒延迟的工作 jsfiddle,我不会尝试从该视图中完全收集视图模型并在其中插入数据列表,这有点像你的举动:) 乍一看我看到很多返回代码,你有没有考虑过一个你可能/不递归使用的模板?它会大大缩短这个视图
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多