ホームページ  >  記事  >  ウェブフロントエンド  >  jQuery_jquery に基づいて高パフォーマンスの TreeView (asp.net) を作成する

jQuery_jquery に基づいて高パフォーマンスの TreeView (asp.net) を作成する

WBOY
WBOYオリジナル
2016-05-16 18:10:24937ブラウズ

私のプロジェクト実践によれば、いくつかの重要なポイントがあります:

1: 静的ツリーをサポートします。つまり、すべてのデータを一度にクライアントにロードします。
2: 非同期ツリー。つまり、一度に 1 つまたは複数のレベルのノードのみがロードされ、子ノードはデータを非同期的にロードできます。
3: 選択 (組織の選択、データ ディクショナリ項目の選択など) などに使用されるチェックボックス ツリー (静的ツリーまたは非同期ツリーの場合があります)。ノード カスケードをサポートするのが最善です (これが困難です)
4: 大量のデータを運ぶことができ、良好なパフォーマンスを発揮します
5: 主流のブラウザーで良好に実行できます

次に、私が構築したい TreeView は、これら 5 つの主要な指標を達成することです。

まずレンダリングを見てみましょう

image

上の写真は中国の行政区のデータ ツリーで、合計 3500 のノードがあります。

それでは仕事を始めます

1: 最初に決定されたノードの Dom 構造 (つまり、ノードの構築にどのような HTML が使用されるか)

  • より一般的なのは、テーブル内のテーブルです (このスタイルは制御しやすいですが、大量のデータと深い層のツリーでは、この構造は間違いなくそれに耐えることができません)
  • LI をカバーする比較的新しい方法もあります。これは、現在多くの書籍で採用されている方法です。利点は、構造がシンプルで明確であることです。 Js ブラウザでもツリーの形状を表示できる場合はサポートされません (この状況は実際には無視できます)。ただし、IE、特に IE6 (IE7 および 8) では、Jquery.treeview のノードを内部要素で開くことができません。一定の深さに達すると開きます)、奇妙な現象が発生します(インデントにパディングが使用されているためだと思います、margin-left:負の値でアイコンの位置を制御しますが、修正も困難です)、この場合この問題は、ブックが変形している場合 (Jquery.treeview) に発生します。この問題は、ノードの幅を設定することによってのみ解決できます。

image

JQuery.treeviewのノード構造

image

Jquery.TreeView IE6 では、第 3 レベルの位置がずれます

IE8 ではレベル 5 に展開image

    CSDN のナビゲーション ツリーは、次の図に示すように、いくつかの方法もあります (ノードが複雑になりすぎず、CSS が書きやすい)。 >

  • image

2番目の方法も使用しましたが、Jquery.treeviewの問題を回避するために、インデントが空白で埋められました。つまり、インデントされた位置が空白の画像で埋められました

image私のツリーノード構造

ノードの HTML を決定したら、CSS を記述できます。レンダリングでは、ノード構造があり、CSS が記述されます

以下は CSS の完全なコードです


コードをコピーします コードは次のとおりです:

.ie .bbit-tree .bbit-tree-bwrap{
}
.bbit-tree ul,.bbit-tree li
{
list-style-type:なし;
マージン:0px;
パディング:0px;
}
.bbit-tree-body
{
font-size:12px;
}
.bbit-tree-icon、.bbit-tree-ec-icon、.bbit-tree-node-cb、.bbit-tree-elbow-line、.bbit-tree-elbow、.bbit -tree-elbow-end、.bbit-tree-elbow-plus、.bbit-tree-elbow-minus、.bbit-tree-elbow-end-plus、.bbit-tree-elbow-end-minus{
境界線: 0 なし。
高さ: 18px;
マージン: 0;
パディング: 0;
vertical-align: 上;
幅: 16px;
背景リピート: リピートなし;
}
.bbit-tree-node-cb
{
height:16px;
}
.bbit-tree-node-collapsed .bbit-tree-node-icon、.bbit-tree-node-expanded .bbit-tree-node-icon、.bbit-tree-node-leaf 。 bbit-tree-node-icon{
ボーダー: 0 なし;
高さ: 18px;
マージン: 0;
パディング: 0;
vertical-align: 上;
幅: 16px;
背景位置:中心;
背景リピート: リピートなし;
}
.ie .bbit-tree-node-indent img、.ie .bbit-tree-node-icon、.ie .bbit-tree-ec-icon {
vertical-align:middle !重要;
}
.bbit-tree-noicon .bbit-tree-node-icon{
width:0;高さ:0;
}
/* 線スタイルはありません。線のない样式 */
.bbit-tree-no-lines .bbit-tree-elbow{
background:transparent;
}
.bbit-tree-no-lines .bbit-tree-elbow-end{
背景:透明;
}
.bbit-tree-no-lines .bbit-tree-elbow-line{
背景:透明;
}
/* Arrows Vista 系统树の样式のみ箭头*/
.bbit-tree-arrows .bbit-tree-elbow{
background:transparent;
}
.bbit-tree-arrows .bbit-tree-elbow-plus{
background:transparent no-repeat 0 0;
}
.bbit-tree-arrows .bbit-tree-elbow-minus{
background:transparent no-repeat -16px 0;
}
.bbit-tree-arrows .bbit-tree-elbow-end{
背景:透明;
}
.bbit-tree-arrows .bbit-tree-elbow-end-plus{
background:transparent no-repeat 0 0;
}
.bbit-tree-arrows .bbit-tree-elbow-end-minus{
background:transparent no-repeat -16px 0;
}
.bbit-tree-arrows .bbit-tree-elbow-line{
背景:透明;
}
.bbit-tree-arrows .bbit-tree-ec-over .bbit-tree-elbow-plus{
background-position:-32px 0;
}
.bbit-tree-arrows .bbit-tree-ec-over .bbit-tree-elbow-minus{
background-position:-48px 0;
}
.bbit-tree-arrows .bbit-tree-ec-over .bbit-tree-elbow-end-plus{
background-position:-32px 0;
}
.bbit-tree-arrows .bbit-tree-ec-over .bbit-tree-elbow-end-minus{
background-position:-48px 0;
}
.bbit-tree-elbow-plus、.bbit-tree-elbow-minus、.bbit-tree-elbow-end-plus、.bbit-tree-elbow-end-minus{
カーソル:ポインタ;
}
.ie ul.bbit-tree-node-ct{
font-size:0;
行の高さ:0;
ズーム:1;
}
.bbit-tree-node{
white-space: nowrap;
}
.bbit-tree-node-el {
line-height:18px;
カーソル:デフォルト;
/* カーソル:ポインタ;*/
}
.bbit-tree-node a{
text-decoration:none;
-khtml-user-select:none;
-moz-user-select:none;
-webkit-user-select:ignore;
-kthml-user-focus:normal;
-moz-user-focus:normal;
-moz-outline: 0 なし;
概要:0 なし。
}
.bbit-tree-node スパン{
text-decoration:none;
パディング:1px 3px 1px 2px;
}
.bbit-tree-node .bbit-tree-node-disabled .bbit-tree-node-icon{
-moz-opacity: 0.5;
不透明度:.5;
フィルター: alpha(opacity=50);
}
.bbit-tree-node .bbit-tree-node-inline-icon{
背景:透明;
}
.bbit-tree-node a:hover{
text-decoration:none;
}

/* ie rootVisible:false の問題を修正、一个IEdebug を修正 */
.bbit-tree-root {
zoom:1;
}

/***********これがアイコンです。ここで置き換えることができます********************/
.bbit-tree-node-expanded .bbit-tree-node-icon{
background-image:url(images/tree) /フォルダーを開く.gif);
}
.bbit-tree-node-leaf .bbit-tree-node-icon{
背景画像:url(images/tree/leaf.gif);
}
.bbit-tree-node-collapsed .bbit-tree-node-icon{
background-image:url(images/tree/folder.gif);
}
.bbit-tree-node-loading .bbit-tree-node-icon{
背景画像:url(images/tree/loading.gif) !重要;
}
.bbit-tree-node .bbit-tree-node-inline-icon {
背景画像: なし;
}
.bbit-tree-node-loading a scan{
font-style: italic;
カラー:#444444;
}
.bbit-tree-lines .bbit-tree-elbow{
background-image:url(images/tree/elbow.gif);
}
.bbit-tree-lines .bbit-tree-elbow-plus{
background-image:url(images/tree/elbow-plus.gif);
}
.bbit-tree-lines .bbit-tree-elbow-minus{
background-image:url(images/tree/elbow-minus.gif);
}
.bbit-tree-lines .bbit-tree-elbow-end{
background-image:url(images/tree/elbow-end.gif);
}
.bbit-tree-lines .bbit-tree-elbow-end-plus{
background-image:url(images/tree/elbow-end-plus.gif);
}
.bbit-tree-lines .bbit-tree-elbow-end-minus{
background-image:url(images/tree/elbow-end-minus.gif);
}
.bbit-tree-lines .bbit-tree-elbow-line{
background-image:url(images/tree/elbow-line.gif);
}
.bbit-tree-no-lines .bbit-tree-elbow-plus{
background-image:url(images/tree/elbow-plus-nl.gif);
}
.bbit-tree-no-lines .bbit-tree-elbow-minus{
background-image:url(images/tree/elbow-minus-nl.gif);
}
.bbit-tree-no-lines .bbit-tree-elbow-end-plus{
background-image:url(images/tree/elbow-end-plus-nl.gif);
}
.bbit-tree-no-lines .bbit-tree-elbow-end-minus{
background-image:url(images/tree/elbow-end-minus-nl.gif);
}
.bbit-tree-arrows .bbit-tree-elbow-plus{
background-image:url(images/tree/arrows.gif);
}
.bbit-tree-arrows .bbit-tree-elbow-minus{
background-image:url(images/tree/arrows.gif);
}
.bbit-tree-arrows .bbit-tree-elbow-end-plus{
background-image:url(images/tree/arrows.gif);
}
.bbit-tree-arrows .bbit-tree-elbow-end-minus{
background-image:url(images/tree/arrows.gif);
}
/*TreeNode 选中の無効な一部の色、文字样式*/
.bbit-tree-node{
color:#000;
フォント: 通常の 11 ピクセルの arial、tahoma、helvetica、sans-serif;
}
.bbit-tree-node a{
color:#000;
}
.bbit-tree-node スパン{
color:#000;
}
.bbit-tree-node .bbit-tree-node-disabled スパン{
color:gray !重要;
}
.bbit-tree-node .bbit-tree-node-over {
背景色: #eee;
}
.bbit-tree-node .bbit-tree-selected {
背景色: #d9e8fb;
}

上面了树的基本样式外,定义了一个有+号带line的样式和+号不带line的样式

image 这就是那个+号带line的样式

css中所用到的所有图片

arrows elbow elbow-end elbow-end-minus elbow-end-minus-nl elbow-end-plus elbow-end-plus-nl elbow-line elbow-minus elbow-minus-nl elbow-plus elbow-plus-nl folder folder-open leaf loading

checkbox_2 checkbox_0 checkbox_1

2: データ構造を決定します

コードをコピーします コードは次のとおりです:

var menudata = [{
id: "0.1", // 一意の ID で十分です
text: "Beyondbit UI Demo",
hasChildren: true,
isexpand : true,
complete: true,
ChildNodes: [{
id: "0.1.1",
text: "日付選択",
hasChildren: true,
isexpand: false、
complete: true、
ChildNodes: [{
id: "0.1.1.1"、
text: "Control Demo"、
value: "Testpages/datepickerDemo.htm"、
hasChildren: false、
isexpand: false、
complete: true、
ChildNodes: null
}、
...
]

このような構造は、最初の利点は、データ自体が階層的であることです。これは、後続のカスケード関連付けでわかります。
3: 面が完成したら、裏地の作成とスクリプトの作成を開始します。 (Javascript)
I am JQuery が支持者を増やしているので、当然 js フレームワークも Jquery を使用します
まず完全なコードをアップロードし、それを 1 つずつ解析します
コードをコピーします コードは次のとおりです:

/****************************************
author:xuanye.wan@gmail.com
page:http://xuanye.cnblogs.com/
***************************************/
(function($) {
$.fn.swapClass = function(c1, c2) {
return this.removeClass(c1).addClass(c2);
}
$.fn.switchClass = function(c1, c2) {
if (this.hasClass(c1)) {
return this.swapClass(c1, c2);
}
else {
return this.swapClass(c2, c1);
}
}
$.fn.treeview = function(settings) {
var dfop =
{
method: "POST",
datatype: "json",
url: false,
cbiconpath: "/images/icons/",
icons: ["checkbox_0.gif", "checkbox_1.gif", "checkbox_2.gif"],
showcheck: false, //是否显示选择
oncheckboxclick: false, //当checkstate状态变化时所触发的事件,但是不会触发因级联选择而引起的变化
onnodeclick: false,
cascadecheck: true,
data: null,
clicktoggle: true, //点击节点展开和收缩子节点
theme: "bbit-tree-arrows" //bbit-tree-lines ,bbit-tree-no-lines,bbit-tree-arrows
}
$.extend(dfop, settings);
var treenodes = dfop.data;
var me = $(this);
var id = me.attr("id");
if (id == null || id == "") {
id = "bbtree" + new Date().getTime();
me.attr("id", id);
}
var html = [];
buildtree(dfop.data, html);
me.addClass("bbit-tree").html(html.join(""));
InitEvent(me);
html = null;
//预加载图片
if (dfop.showcheck) {
for (var i = 0; i < 3; i++) {
var im = new Image(16,16);
im.src = dfop.cbiconpath + dfop.icons[i];
}
}
//region
function buildtree(data, ht) {
ht.push("
"); // Wrap ;
ht.push("
"); // body ;
ht.push("
    "); //root
    var l = data.length;
    for (var i = 0; i < l; i++) {
    buildnode(data[i], ht, 0, i, i == l - 1);
    }
    ht.push("
"); // root and;
ht.push("
"); // body end;
ht.push("
"); // Wrap end;
}
//endregion
function buildnode(nd, ht, deep, path, isend) {
ht.push("
  • ");
    ht.push("
    var cs = [];
    cs.push("bbit-tree-node-el");
    if (nd.hasChildren) {
    cs.push(nd.isexpand ? "bbit-tree-node-expanded" : "bbit-tree-node-collapsed");
    }
    else {
    cs.push("bbit-tree-node-leaf");
    }
    if (nd.classes) { cs.push(nd.classes); }
    ht.push(" class='", cs.join(" "), "'>");
    //span indent
    ht.push("");
    if (deep == 1) {
    ht.push("");
    }
    else if (deep > 1) {
    ht.push("");
    for (var j = 1; j < deep; j++) {
    ht.push("");
    }
    }
    ht.push("
    ");
    //img
    cs.length = 0;
    if (nd.hasChildren) {
    if (nd.isexpand) {
    cs.push(isend ? "bbit-tree-elbow-end-minus" : "bbit-tree-elbow-minus");
    }
    else {
    cs.push(isend ? "bbit-tree-elbow-end-plus" : "bbit-tree-elbow-plus");
    }
    }
    else {
    cs.push(isend ? "bbit-tree-elbow-end" : "bbit-tree-elbow");
    }
    ht.push("");
    ht.push("");
    //checkbox
    if (dfop.showcheck && nd.showcheck) {
    if (nd.checkstate == null || nd.checkstate == undefined) {
    nd.checkstate = 0;
    }
    ht.push("");
    }
    //a
    ht.push("");
    ht.push("", nd.text, "");
    ht.push("
    ");
    ht.push("
    ");
    //子
    if (nd.hasChildren) {
    if (nd.isexpand) {
    ht.push("
      ");
      if (nd.ChildNodes) {
      var l = nd .ChildNodes.length;
      for (var k = 0; k nd.ChildNodes[k].parent = nd; 、深さ 1、パス "." k, k == l - 1);
      }
      }
      ht.push("
    "); {
    ht.push("
      ");
      }
      }
      ht.push("
    • ;");
      nd.render = true;
      }
      function getItem(path) {
      var ap = path.split(".");
      var t =treenodes;
      for (var i = 0; i
      if (i == 0) {
      t = t[ap[i]]}
      else {
      t = t.ChildNodes[ap[i]];
      }
      }
      return t;
      }
      関数 check(項目、状態、型) {
      var pstate = item.checkstate;
      if (type == 1) {
      item.checkstate = state;
      }
      else {// 上溯
      var cs = item.ChildNodes;
      var l = cs.length;
      var ch = true;
      for (var i = 0; i if ((state == 1 && cs[i].checkstate != 1) || state == 0 && cs[i] .checkstate != 0) {
      ch = false;
      休憩;
      }
      }
      if (ch) {
      item.checkstate = state;
      }
      else {
      item.checkstate = 2;
      }
      }
      //change show
      if (item.render && pstate != item.checkstate) {
      var et = $("#" id "_" item.id "_cb");
      if (et.length == 1) {
      et.attr("src", dfop.cbiconpath dfop.icons[item.checkstate]);
      }
      }
      }
      //遍历子节点
      function cascade(fn, item, args) {
      if (fn(item, args, 1) != false) {
      if (item.ChildNodes != null && item.ChildNodes.length > 0) {
      var cs = item.ChildNodes;
      for (var i = 0, len = cs.length; i < len; i ) {
      cascade(fn, cs[i], args);
      }
      }
      }
      }
      //泡立つ祖先
      function bubble(fn, item, args) {
      var p = item.parent;
      while (p) {
      if (fn(p, args, 0) === false) {
      break;
      }
      p = p.parent;
      }
      }
      function nodeclick(e) {
      var path = $(this).attr("tpath");
      var et = e.target || e.src要素;
      var item = getItem(path);
      //デバッガー;
      if (et.tagName == "IMG") {
      // 号必要展开
      if ($(et).hasClass("bbit-tree-elbow-plus") || $(et ).hasClass("bbit-tree-elbow-end-plus")) {
      var ul = $(this).next(); //"bbit-tree-node-ct"
      if (ul.hasClass("bbit-tree-node-ct")) {
      ul.show();
      }
      else {
      var deep = path.split(".").length;
      if (item.complete) {
      item.ChildNodes != null && asnybuild(item.ChildNodes, deep, path, ul, item);
      }
      else {
      $(this).addClass("bbit-tree-node-loading");
      asnyloadc(ul, item, function(data) {
      item.complete = true;
      item.ChildNodes = data;
      asnybuild(data, deep, path, ul, item);
      });
      }
      }
      if ($(et).hasClass("bbit-tree-elbow-plus")) {
      $(et).swapClass("bbit-tree-elbow-plus "、"bbit-tree-elbow-minus");
      }
      else {
      $(et).swapClass("bbit-tree-elbow-end-plus", "bbit-tree-elbow-end-minus");
      }
      $(this).swapClass("bbit-tree-node-collapsed", "bbit-tree-node-expanded");
      }
      else if ($(et).hasClass("bbit-tree-elbow-minus") || $(et).hasClass("bbit-tree-elbow-end-minus")) { //- 号必要收缩
      $(this).next().hide();
      if ($(et).hasClass("bbit-tree-elbow-minus")) {
      $(et).swapClass("bbit-tree-elbow-minus", "bbit-tree-elbow -プラス");
      }
      else {
      $(et).swapClass("bbit-tree-elbow-end-minus", "bbit-tree-elbow-end-plus");
      }
      $(this).swapClass("bbit-tree-node-expanded", "bbit-tree-node-collapsed");
      }
      else if ($(et).hasClass("bbit-tree-node-cb")) // 点击了Checkbox
      {
      var s = item.checkstate != 1 ? 1:0;
      var r = true;
      if (dfop.oncheckboxclick) {
      r = dfop.oncheckboxclick.call(et, item, s);
      }
      if (r != false) {
      if (dfop.cascadecheck) {
      //遍历
      cascade(check, item, s);
      //上溯
      bubble(check, item, s);
      }
      else {
      check(item, s, 1);
      }
      }
      }
      }
      else {
      if (dfop.citem) {
      $("#" id "_" dfop.citem.id). RemoveClass("bbit-tree-selected");
      }
      dfop.citem = アイテム;
      $(this).addClass("bbit-tree-selected");
      if (dfop.onnodeclick) {
      dfop.onnodeclick.call(this, item);
      }
      }
      }
      function asnybuild(nodes, deep, path, ul, pnode) {
      var l = nodes.length;
      if (l > 0) {
      var ht = [];
      for (var i = 0; i nodes[i].parent = pnode;
      buildnode(nodes[i], ht, deep, path "." i, i == l - 1);
      }
      ul.html(ht.join(""));
      ht = null;
      InitEvent(ul);
      }
      ul.addClass("bbit-tree-node-ct").css({ "z-index": 0、位置: "static"、可視性: "visible"、top: "auto" 、左: "自動"、表示: "" });
      ul.prev().removeClass("bbit-tree-node-loading");
      }
      function asnyloadc(pul, pnode, callback) {
      if (dfop.url) {
      var param = builparam(pnode);
      $.ajax({
      type: dfop.method,
      url: dfop.url,
      data: param,
      dataType: dfop.datatype,
      success: callback,
      エラー: function(e) {alert("エラーが発生しました!") }
      });
      }
      }
      function builparam(node) {
      var p = [{ name: "id", value: encodeURIComponent(node.id) }
      , { name: "text" , 値: encodeURIComponent(node.text) }
      , { 名前: "値", 値: encodeURIComponent(node.value) }
      , { 名前: "checkstate", 値: node.checkstate}];
      p を返します。
      }
      function InitEvent(parent) {
      var ノード = $("li.bbit-tree-node>div",parent);
      nodes.each(function(e) {
      $(this).hover(function() {
      $(this).addClass("bbit-tree-node-over");
      }, function() {
      $(this).removeClass("bbit-tree-node-over");
      })
      .click(nodeclick)
      .find("img.bbit -tree-ec-icon").each(function(e) {
      if (!$(this).hasClass("bbit-tree-elbow")) {
      $(this).hover(function) () {
      $(this).parent().addClass("bbit-tree-ec-over");
      }, function() {
      $(this).parent().removeClass ("bbit-tree-ec-over");
      }
      });
      }
      function getck(items, c, fn) {
      for (var i = 0, l = items.length; i < l; i ) {
      items[i].checkstate == 1 && c.push(fn(items[i]));
      if (items[i].ChildNodes != null && items[i].ChildNodes.length > 0) {
      getck(items[i].ChildNodes, c, fn);
      }
      }
      }
      me[0].t = {
      getSelectedNodes: function() {
      var s = [];
      getck(treenodes, s, function(item) { return item });
      s を返します。
      },
      getSelectedValues: function() {
      var s = [];
      getck(treenodes, s, function(item) { return item.value });
      s を返します。
      },
      getCurrentItem: function() {
      return dfop.citem;
      }
      };
      返してください。
      }
      //すべての選択中のポイントの値数グループを取得します
      $.fn.getTSVs = function() {
      if (this[0].t) {
      return this[0 ].t.getSelectedValues();
      }
      null を返します。
      }
      //すべての選択中の項目数グループを取得
      $.fn.getTSNs = function() {
      if (this[0].t) {
      return this[0 ].t.getSelectedNodes();
      }
      null を返します。
      }
      $.fn.getTCT = function() {
      if (this[0].t) {
      return this[0].t.getCurrentItem();
      }
      null を返します。
      }
      })(jQuery);


      最初のステップ: 当然、すべての Jquery のコントロールの最初のステップは、このアーキテクチャを搭載し、JQuery と $save 回避パケットを回避し、その他のクラスのクラッシュを回避し、パラメータを受け取ります (オブジェクトです) )


      复制代码代码如下:
      ;(function($) {
      / /また$.fn.extend(treeview:function(setting){})
      $.fn.treeview = function(setting) {
      }
      })(jQuery); を使用することもできます。


      那第 2 番目のステップ: 制御プログラム追加のパラメータ默认パラメータ、同時にメソッド $.extend を使用できるようにするためのパラメータをカバーする (結果がない場合は使用默认)


      复制代 代码如下:
      var dfop ={
      method: "POST",//默认採用POST提交データ
      datatype: "json",//データ型はjson
      url: false,//异步请要求的url
      cbiconpath: "/images/icons/",//チェックボックスアイコンの目录位置
      アイコン: ["checkbox_0.gif", "checkbox_1.gif", "checkbox_2.gif"],//checkbxo三态的画像
      showcheck: false, // チェックボックスの有無
      oncheckboxclick: false, //ポイント击checkbox時にトリガーされるイベント
      onnodeclick: false,//ポイント击nodeトリガーされる時間
      cascadecheck: true,//否か启用级联
      data: null,//初期化データベース
      テーマ: "bbit-tree-arrows" //三种风格备选bbit-tree-lines ,bbit-tree-no-lines,bbit-tree-arrows
      }
      //用传进来的パラメータ覆盖默认,没传则 保持
      $.extend(dfop, settings);


      第三段階: 承認されたデータの HTML (私たちの分析ポイントの Dom 構造、データのデータ構造に基づいて、ポイントを生成するのは非常に珍しい) を生成し、現在のコンテナーに追加します。このイベントには非常に重要な場所があり、ダウンロード (展開のないアクセスポイント HTML は生成されません) されており、これはパフォーマンスの向上に必要なデータを要求します。さらに重要な点は、すべての展開ポイントの HTML を一度に生成し、append 操作ではなく、innerHTML プロパティを介して Dom を生成することです。これは、innerHTML を直接操作するため、dom 生成されたメソッドよりも N 倍早く操作できるためです。越多,N越大),切记切记!

      vartreenodes = dfop.data; //内部データの場合、実際には dfop.data を直接使用できます
      var me = $(this)
      var id = me.attr("id ");
      if (id == null || id == "") {
      id = "bbtree" new Date().getTime();
      me.attr("id", id );
      }//グローバルに一意の ID
      var html = [];
      buildtree(dfop.data, html);//展開されたノードの HTML を生成し、配列にプッシュします。 me.addClass("bbit-tree").html(html.join(""));
      InitEvent(me);//初期化イベント


      ノード生成プロセス中に、簡単に取得できるようにノードのパスも同時に生成できます


      コードをコピーしますコードは次のとおりです。
      if (nd.hasChildren) { //子ノードが存在します
      if (nd.isexpand) {//同時に、ノードが展開すると、子ノードが出力されます
      ht.push("
        ");
        if (nd.ChildNodes) {
        var l = nd.ChildNodes.length;
        for (var k = 0; k < l; k ) {//再帰的に呼び出してノードのパスを生成します
        nd.ChildNodes[k].parent = nd;
        buildnode(nd.ChildNodes[k], ht, deep 1, path "." k, k == l - 1);
        }
        }
        ht.push("
      ");
      }
      else { //それ以外の場合は出力保留状態になります
      ht.push("
        ");
        }
        }


        イベントを登録し、パラメータparentを受け入れます。つまり、特定の親ノードからイベントをアタッチします(ホバー効果のため、イベントは各ノード上にあります。効果がキャンセルされた場合、イベントはツリーに直接アタッチされ、イベントの srcElement (パフォーマンスをわずかに向上させることができます)


        function InitEvent(parent) {
        var nodes = $("li.bbit-tree-node>div",parent);
        nodes.each(function (e) {
        $(this). hover(function() {
        $(this).addClass("bbit-tree-node-over"); //マウスフローティングノードのスタイル変更
        }, function() {
        $(this ).removeClass("bbit-tree-node-over");
        })
        .click(nodeclick)// ノードの onclick イベント、これが重要なポイントです Oh
        .find("img.bbit -tree-ec-icon").each(function(e) { // ビスタスタイルを実現するための矢印のホバーイベント
        if (!$(this) .hasClass("bbit-tree-elbow") ) {
        $(this).hover(function() {
        $(this).parent().addClass("bbit-tree-ec-over" );
        }, function() {
        $(this).parent().removeClass("bbit-tree-ec-over");
        }
        });


        ここで最も重要なことは、ノードのクリック イベントです。これは、ツリーの拡張や縮小など、多くのことを処理する必要があるためです (子ノードが存在しない場合、ただし、hasChildren が true で、complete 属性が true ではない場合、子ノードは非同期でロードする必要があります。子ノードは存在するが、Render がない場合は、チェックボックスをクリックするとカスケード イベントがトリガーされ、oncheckbox がトリガーされます。 「その他」をクリックすると、条件付きのnodeonclickイベントがトリガーされます。これらはすべて、前のイベントのソース要素のクラスによってクリックされたオブジェクトを区別します



        コードをコピーします
        コードは次のとおりです:

        function nodeclick(e) {
        var path = $(this).attr("tpath");//ノードパスを取得します
        var et = e.target || ; //イベントソースを取得
        var item = getItem(path);//パスに基づいてノードデータを取得
        //debugger
        if (et.tagName == "IMG") {
        / 記号は展開する必要があり、プラス記号とマイナス記号は処理されます
        if ($(et).hasClass("bbit-tree-elbow-plus") || $(et).hasClass("bbit- Tree-elbow-end-plus ")) {
        var ul = $(this).next(); //"bbit-tree-node-ct"
        if (ul.hasClass("bbit-tree -node-ct")) {
        ul.show();
        }
        else {
        var deep = path.split(".").length;
        if (item. complete) {
        item .ChildNodes != null && asnybuild(item.ChildNodes, deep, path, ul, item);
        }
        else {
        $(this).addClass("bbit-ツリーノードロード") ;
        asnyloadc(ul, item, function(data) {
        item.complete = true;
        item.ChildNodes = data;
        asnybuild(data, deep, path , ul, item);
        }
        }
        if ($(et).hasClass("bbit-tree-elbow-plus")) {
        $(et ).swapClass("bbit-tree-elbow-plus", "bbit-tree-elbow-minus");
        }
        else {
        $(et).swapClass("bbit-tree-elbow -end-plus", " bbit-tree-elbow-end-minus");
        }
        $(this).swapClass("bbit-tree-node-collapsed", "bbit-tree-node- Expanded");
        }
        else if ($(et).hasClass("bbit-tree-elbow-minus") || $(et).hasClass("bbit-tree-elbow-end-minus ")) { //- 数値を縮小する必要があります
        $(this).next().hide();
        if ($(et).hasClass("bbit-tree-elbow-minus" )) {
        $(et) .swapClass("bbit-tree-elbow-minus", "bbit-tree-elbow-plus")
        }
        else {
        $(et); .swapClass("bbit-tree-elbow-end-minus", "bbit-tree-elbow-end-plus");
        }
        $(this).swapClass("bbit-tree-node-expanded ", "bbit-tree-node-collapsed ");
        }
        else if ($(et).hasClass("bbit-tree-node-cb")) // チェックボックスがクリックされています
        {
        var s = item.checkstate ! = 1 ? 1 : 0;
        var r = true;
        if (dfop.oncheckboxclick) { // 設定された関数
        r = dfop.oncheckboxclick. call(et, item, s);
        }
        if (r != false) {//戻り値が false でない場合、つまり checkbxo の変更が有効な場合
        if (dfop.cascadecheck) ) {//カスケードのトリガーを許可します
        //Traversal
        cascade(check, item, s);//下方向に関連付けます
        //上に関連付けます
        bubble(check, item, s) / /上向きに関連付けます
        }
        else {
        check(item, s, 1);//それ以外の場合は、内に留めておいてください
        }
        }
        }
        }
        else {//他の場所をクリックしました
        if (dfop.citem ) { //前の現在のノード
        $("#" id "_" dfop.citem.id).removeClass("bbit-tree-selected") ;
        }
        dfop.citem = item ;//今回は現在のノード
        $(this).addClass("bbit-tree-selected");
        if (dfop.onnodeclick) {
        dfop.onnodeclick.call(this, item) ;
        }
        }
        }

        非同期リクエストのコードの一部を展開しないでください。非常に複雑なので、詳細は説明しません。重要な点は、カスケード
        レベルについて説明することです。対処すべき問題は 2 つあります。1 つ目は、子ノードをたどることです。2 つ目は、子ノードを追跡することです。データ構造のため、両方の操作は非常に簡単です

        コードをコピーします コードは次のとおりです:
        //子ノードを走査
        function cascade(fn, item, args) {
        if (fn (item, args, 1) != false) {
        if (item.ChildNodes) != null && item.ChildNodes.length > 0) {
        var cs = item.ChildNodes;
        for (var i = 0, len = cs.length; i cascade(fn, cs[i], args);
        }
        }
        }
        }
        //バブルの祖先
        関数 bubble(fn, item, args) {
        var p = item.parent;
        while (p) {
        if (fn(p, args, 0) === false) {
        break; p.parent;
        }
        }


        チェックは、ノードが見つかるとトリガーされます。このコールバック関数は、現在のノードのステータスを決定するために使用されます。詳細については、以下のコードを参照してください。プロセスがよりわかりやすく説明されています



        コードをコピー
        コードは次のとおりです:

        function check(item, state, type) {
        var pstate = item.checkstate; //Current state
        if (type == 1) {
        item.checkstate = state; //If you are traversing child nodes, the child will be whatever the parent is
        }
        else {// Backtracking, this is a bit more complicated
        var cs = item.ChildNodes; //Get all the children of the current node Node
        var l = cs.length;
        var ch = true; //Whether it is not an intermediate state half-selected
        for (var i = 0; i < l; i ) {
        if ( (state == 1 && cs[i].checkstate != 1) || state == 0 && cs[i].checkstate != 0) {
        ch = false;
        break;//his As long as one of the child nodes is not selected, then it is half-selected
        }
        }
        if (ch) {
        item.checkstate = state; // If it is not half-selected, then what is the child node? What is
        }
        else {
        item.checkstate = 2; //Half selection
        }
        }
        //change show If the node has been output, but its before and after states are different , then change the display of checkbxo
        if (item.render && pstate != item.checkstate) {
        var et = $("#" id "_" item.id "_cb");
        if (et.length == 1) {
        et.attr("src", dfop.cbiconpath dfop.icons[item.checkstate]);
        }
        }
        }

        At this point, the main function of our tree has been fully realized. Others are to expose some methods, etc. You can see the code for details. In the example, two are exposed, one is all the currently selected nodes, and the other is the current node.

        You can check the examples in the article through the following website. I apologize if selected is spelled wrong! Windows azure deployment is still troublesome and I am too lazy to modify 3500 nodes to be loaded at one time. You can click on the root node to select all to see the speed

        http://jscs.cloudapp.net/ControlsSample/BigTreeSample

        Asynchronous loading and on-demand loading are also very common. The SQL Azure server is used in the United States, so asynchronous loading may be a bit slow, but local data sources are instantaneous

        http://jscs.cloudapp.net/ControlsSample/TreeAsnySample

        FAQ:

        1: How to set a different icon for each node?

        Answer:

        In fact, there is no need to extend it, it is supported by itself, but there is no explanation. Let’s take a look at this code? Is there such a sentence in the BuildNode method?
        if (nd.classes) { cs.push(nd.classes); }

        You can set the attribute classes in the data structure of the node, which will be added to the node as a special Css Class of the node . Then taking advantage of this, you can set the icon of the node

        image

        Then just write a Style

        image

        Let’s take a look at the final effect?

        image

        声明:
        この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。