1

この図でわかるように、Visual Studio 2012 のソリューション エクスプローラーと同様に動作する HTML ツリービューを作成しました。このツリーのすべてのノードは、コンテナーの残りのスペースを埋めるために引き伸ばされます。

Visual Studio 2012 ソリューション エクスプローラー

この動作を実現するために、Javascript を使用して順不同リストを作成し、ツリーにデータを追加しています。DOM 構造は次のようになります。

<ul>
   <li>
      <input type="checkbox" id="node_xy" />
      <label for="node_xy" /> <!-- expand/collapse button -->
      <a href="javascript:nodeClickHandler();"> <!-- node text --> </a>
      <ul>
         <!-- subtree with li elements... -->
      </ul>
   </li>
</ul>

ツリーにデータを入力した後、Javascript (jQuery) を使用して各ノードの幅を調整し、コンテナーの残りのスペースを埋めます。コンテナーの幅は固定されていますが、(Visual Studio のように) スクロール可能であるため、ツリーの最大幅が変更される可能性があるため、ユーザーがツリー内のノードを展開または折りたたむたびに、同じ幅調整手順を実行する必要があります。コードの幅調整部分は次のようになります。

updateLayout: function (containerWidth) {
    var self = $(this);
    self.find('.treeview a').css('width', ''); /* remove the width property for the next calculation */

    var maxAWidth = $('.treeview a').max(function () {
        return $(this).offset().left + $(this).outerWidth();
    });

    var targetWidth = containerWidth || $('.treeview').width();
    targetWidth = Math.max(targetWidth, maxAWidth);

    $('.treeview a').each(function () {
        var left = $(this).offset().left;
        $(this).outerWidth(targetWidth - left);
    });
}

正常に動作しますが、ツリーに多数 (数百または数千) のノードがあり、ユーザーがノードを展開または折りたたむ場合は非常に遅くなります。updateLayoutメソッドがツリービューの下の完全な DOM ツリーをトラバースするため、これらのケースではパフォーマンスが非常に悪くなります (展開/折りたたみごとに 1 ~ 2 秒の計算) 。この種のトラバースを使用しない、この「ストレッチ」問題に対する他の解決策はあるのでしょうか? ある種の純粋なCSSマジックでこの問題を解決できればいいのですが、まったく不可能のようです...

アップデート:

標準の jQuery 最適化 (クエリ結果を変数に抽出するなど) は機能しません。たとえば、次のコードは古いコードよりも高速ではありません。

    updateLayout: function (containerWidth) {
        var self = $(this);
        var treeviewLinks = self.find('.treeview a').css('width', '').get();

        var maxAWidth = -Infinity;
        for(var i = 0; i < treeviewLinks.length; i++) {
            var link = $(treeviewLinks[i]);
            if(link.offset().left + link.outerWidth() > maxAWidth)
                maxAWidth = link.offset().left + link.outerWidth();
        }
        var targetWidth = containerWidth || $('.treeview').width();
        targetWidth = Math.max(targetWidth, maxAWidth);

        for(var i = 0; i < treeviewLinks.length; i++) {
            var link = $(treeviewLinks[i]);
            link.outerWidth(targetWidth - link.offset().left);
        }
    }

ただし、updateLayoutツリー内のすべてのノードに同じ幅を使用することで、ステップを高速化できました。

    updateLayout: function (containerWidth) {
        var treeviewLinks = $(this).find('.treeview a');
        $('#treeViewItemStyle').remove();

        var maxAWidth = treeviewLinks.max(function () {
            return $(this).offset().left + $(this).outerWidth();
        });

        var targetWidth = containerWidth || $('.treeview').width();
        targetWidth = Math.max(targetWidth, maxAWidth);
        $('<style id="treeViewItemStyle" type="text/css"> #treeview a { width: '
            + (targetWidth - 19) + 'px !important; } </style>')
        .appendTo('head');
    }

この最適化により、updateLayout実行速度は速くなりますが、幅が同じであるため、コンテナーの最終的な幅は必要以上に大きくなります。私は現在、それを改善するための他のソリューションを探しています...

4

1 に答える 1

0

まず第一に、あなたは完全に不必要な多くの重複したクエリを使用しました.

$('.treeview a')

変数に入れて再利用します。それ以外は、DOM 全体をトラバースするのではなく、変更が必要な要素のみを選択するようにしてください。たとえば、ユーザーが最近クリックした要素のサブリストを選択するだけです。

于 2013-09-06T11:45:57.080 に答える