私の実際の Web アプリには、フォルダーを表示するツリーがあり、場合によっては、このツリーを jQuery UI ダイアログ内に表示します。私はできる限りすべてを取り除き、問題の例をこのフィドルに入れました:
http://jsfiddle.net/shopguy/gRbef/
ボタン 1 をクリックすると、ダイアログの表示が切り替わります。
ボタン 2 をクリックすると、インライン (ダイアログなし) リストの表示が切り替わります。
ほとんどのテストを Firefox で行っています。ボタン 1 をクリックすると、表示または非表示に約 1.5 秒かかります (非表示でも時間がかかります)。ボタン 2 をクリックするのはほぼ瞬時です。
これは jQuery UI ダイアログの問題ですか。各非表示/表示でDOMを使用して多くのことを行いますか? それとも、テンプレート内にあるため、単なる問題ですか? そのようなテンプレートにあるという理由だけで、KO は dom を再作成しますか?
どちらの場合もテンプレートを使用しますが、ダイアログ バージョンには、ダイアログ自体用の追加のテンプレートが 1 つあります。ただし、どちらもサブフォルダーのテンプレートを使用しています... 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());
});