2

在我真正的网络应用程序中,我有一个显示文件夹的树,在某些情况下,我在 jQuery UI 对话框中显示这棵树。我已经剥离了我所能做的一切,并在这个小提琴中举了一个问题的例子:

http://jsfiddle.net/shopguy/gRbef/

如果单击按钮 1,它将切换对话框的可见性。

如果单击按钮 2,它将切换内联(无对话框)列表可见性。

在 Firefox 中进行大部分测试。单击按钮 1 大约需要 1.5 秒,显示或隐藏(即使隐藏很慢)。单击按钮 2 几乎是即时的。

这是 jQuery UI 对话框的问题吗?它对每个隐藏/显示的 DOM 有很大作用吗?或者这只是一个问题,因为我在模板中有它?KO是否仅仅因为它在这样的模板中而重新创建dom?

这两种情况都使用模板,但对话版本有一个额外的模板,用于对话本身。他们都使用子文件夹的模板......因为我不确定如何使用 KO 进行递归树状布局。

这是小提琴中的主要 HTML,显示了我的带有树形布局的对话框:

<div data-bind="jqDialog: {autoOpen: false, modal: false, width: 350, height: 400, minWidth: 350, minHeight: 300 }, template: { name: 'folderDetailsTemplate' } , openDialog: dlg1"></div>
<script type="text/html" id="folderDetailsTemplate">
List<br />
<ul data-bind="template: { name: 'tmpl1', foreach: folders}"></ul>
</script>
<script type="text/html" id="tmpl1">
<li>
    <a data-bind="visible: expanded">-</a>
    <a data-bind="visible: !expanded">+</a>
    <a>
    <span data-bind="text: name"></span>
    </a>
    <ul data-bind="template: { name: 'tmpl1', foreach: folders}">
    </ul>
</li>
</script>

这是脚本:

   ko.bindingHandlers.jqDialog = {
        init: function (element, valueAccessor) {
            var options = ko.utils.unwrapObservable(valueAccessor());
            $(element).dialog(options);
        }
    };

    ko.bindingHandlers.openDialog = {
        update: function (element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor());
            if (value) {
                $(element).dialog("open");
            } else {
                $(element).dialog("close");
            }
        }
    }

    function Folder(i, l) {
        this.name = "Test Folder " + i;
        this.folders = ko.observableArray();
        this.expanded = true;

        if (i < 4 && l < 4) {
            var fs = new Array();
            for (var x = 0; x < 2; x++) {
                var f = new Folder(x, l + 1);
                fs.push(f);
            }
            this.folders(fs);
        }

    }

    var vm = function () {
        var self = this;
        self.folders = ko.observableArray();
        var fs = new Array();
        for (var x = 0; x < 50; x++) {
            var f = new Folder(x, 0);
            fs.push(f);
        }
        self.folders(fs);
        self.dlg1 = ko.observable();
        self.list1 = ko.observable();

        self.test1 = function () {
            self.dlg1(!self.dlg1());
        }

        self.test2 = function () {
            self.list1(!self.list1());
        }
    }

    $(function () {
        ko.applyBindings(new vm());
    });
4

1 回答 1

1

让它变慢的原因是openDialogtemplate绑定在同一元素的绑定字符串中组合在一起。因此,每次openDialog更新时,模板绑定也会更新并重新呈现您的模板。我喜欢将模板绑定放在嵌套的注释绑定中,如下所示:

<div data-bind="jqDialog: {autoOpen: false, modal: false, width: 350, height: 400, minWidth: 350, minHeight: 300 }, openDialog: dlg1">
        <!-- ko template: 'folderDetailsTemplate' --><!-- /ko -->
</div>

这一切都在这里非常详细:http ://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html

于 2013-02-22T01:16:24.743 回答