使用jsTree实现懒加载

16

我正在尝试在JTree节点展开时动态加载它们。我在 这个页面 的末尾找到了一些文档。

我发现一些解决方案通过循环逐个创建节点,例如 这个。我还没有尝试过,但是看着文档页面,我有一种感觉,就是jstree应该负责循环遍历这些节点。

我发现许多解决方案都使用 plugins: ["json_data"],但是 插件文档页面 并没有提到这个插件。那是一个旧插件吗?已经不再需要了吗?

我的当前实现使用以下代码一次性加载整个树:

$.ajax({
    var pn = $('#project_number').val();
    url : "bomtree?part=" + pn,
    success : function(tree_content) {
        var data = $.parseJSON(tree_content);
        var config = {
            'core' : {
                'data' : data
            }
        };
        $('#bom_tree').jstree(config);
    }
});

我像这样修改了文档页面上的代码:

$(function() {
    var pn = $('#project_number').val();
    $('#tree').jstree({
        'core' : {
            'data' : {
                'url' : function(node) {
                    return '/doc/test2';
                },
                'data' : function(node) {
                    return {
                        'part' : node.id === '#' ? pn : node.id
                    };
                }
            }
        }
    });
});

相同的JSON文本在第一段代码中能够正常工作,但现在在第二段代码中无法正常工作。文档说“格式与上述相同”,所以我没有更改它。

我也尝试返回与示例中相同的数据,这样:

[
       { "id" : "ajson1", "parent" : "#", "text" : "Simple root node" },
       { "id" : "ajson2", "parent" : "#", "text" : "Root node 2" },
       { "id" : "ajson3", "parent" : "ajson2", "text" : "Child 1" },
       { "id" : "ajson4", "parent" : "ajson2", "text" : "Child 2" },
]

但结果是相同的:jQuery在以下行抛出Sizzle.error错误:

Sizzle.error = function( msg ) {
    throw new Error( "Syntax error, unrecognized expression: " + msg );
};

msg的内容是服务器返回的JSON数据。

有什么问题吗?

5个回答

16
“在使用AJAX时,将children设置为boolean true,jsTree将以关闭的方式呈现节点,并在用户打开该节点时进行额外的请求。” 这是来自jstree文档的内容,可以满足您的要求。

10

延伸Nathan的回答,这是一个(非常简约的)示例: 使用懒加载的演示树。

JS:

$('#the_tree').jstree({
    'core' : {
        'data' : {
            'url' : "tree/ajax.php", 
              'data' : function (node) {
                  return { 'id' : node.id };
              }
        }
    },

});

PHP:

header('Content-Type: application/json');

if ( $_GET["id"] === "#" ) { 
    $data = array(
            array( "id" => "ajson1", "parent" => "#", "text" => "Simple root node"  ),
            array( "id" => "ajson2", "parent" => "#", "text" => "Root node 2", "children" => true ),

    );
}

else if ( $_GET["id"] === "ajson2" ) {
    $data = array(
        array( "id" => "ajson3", "parent" => "ajson2", "text" => "Child 1" ),
        array( "id" => "ajson4", "parent" => "ajson2", "text" => "Child 2" )
    );
}

echo json_encode( $data);

只有具有 "children" : true 属性的节点在展开时才会生成获取子节点的请求,其他节点视为叶节点。


2
这对我理解JsTree的结构以及它如何与父项和延迟加载一起工作非常有帮助。你刚刚拯救了我,兄弟 :) - Md Mazedul Islam Khan
2
谢谢您提供这个例子。这终于是我需要的示例,让按需加载起作用了。 - toni rmc

8
我会给你说文档/示例比较粗糙。我还要补充一点,你的困惑源于一个重大升级 - 旧版本 与新版本没有多少共同之处,不幸的是大多数示例都是针对那个旧版本编写的。
好消息是,懒加载已经被支持了,只是不太明显。关键是它在每个节点展开时调用你的 data: 配置。但为了使其工作,URL 函数必须返回给定节点的不同 URL。在下面的代码中,请注意在根节点 (#) 和其他节点中返回不同 URL 的条件。
$('#TreeDiv')
  .jstree({
    core: {
      data: {
        url: function (node) {
          return node.id === '#' ? '/UserAccount/AccountGroupPermissions' 
                                 : '/UserAccount/AccountPermissions/' + node.id;
        },
        type: 'POST'
      }
   },
   plugins : ["checkbox"]
});

从jsTree 3.3.5开始,您可以使用相同的URL并仍然进行延迟加载。下面André Bonna的回答揭示了在“success”属性中设置node.children = true将导致jsTree利用延迟加载并每次展开节点时调用相同的URL。如果只指定一个URL,则将使用该URL。 - barrypicker

5

要实现懒加载,你需要一个后端返回一个带有children属性的JSON对象,该属性包含具有子元素或布尔值true(数组或布尔值)的子节点。如果你在后端使用静态类型语言,代码将会变得很复杂,所以最好在前端处理。以下是AJAX成功回调的示例:

$('#tree').jstree({
    'core' : {
        'data' : {
            'url' : function(node) {
                return '/doc/test2';
            },
            'data' : function(node) {
                return {
                    'part' : node.id === '#' ? pn : node.id
                };
            },
            'success' : function(nodes) {

                var validateChildrenArray = function(node) {

                    if (!node.children || node.children.length === 0) {
                        node.children = true;
                    }
                    else {
                        for (var i = 0; i < node.children.length; i++) {
                            validateChildrenArray(node.children[i]);
                        }
                    }
                };

                for (var i = 0; i < nodes.length; i++) {
                    validateChildrenArray(nodes[i]);
                }
            }
        }
    }
});

通过这样做,您将能够对树进行延迟加载。

非常感谢您,这救了我一天! - phifi

0
我通过结合 "select_node.jstree" 事件和 "create_node" 方法来制作了自定义的懒加载。在选择每个节点时,事件处理程序会检查是否有子节点,并将服务器响应逐个节点地添加到所选节点中。 我的服务器响应与 jstree 的要求不同,这种策略为我节省了大量时间和精力。 希望能对某些人有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接