【问题标题】:JSTREE script execute asynchronouslyJSTREE 脚本异步执行
【发布时间】:2011-09-19 07:38:40
【问题描述】:

我已经在我的项目上实施了 JSTREE 一切正常,但最近我遇到了一个问题,即使我设法解决了它的概念,我仍然不清楚。

这里是什么意思?

JSTREE 代码写在jquery 文档准备函数 像这样

$(document).ready(function() { 
  $("#someid").jstree( { 

    "json_data" : {
      "data" : [{
        "attr" : { "id" : "root" },
        "data" : {
          "title" : "Root",
          "attr" : { "id" : "root","href" : "#" ,"class" : "jstree-clicked" }
        },
        "children" : [
              {
              "attr" : {"id" : "node-1"},
              "data" : {
                "title" : "Node-1",
                "attr" : {"id" : "node-1" ,"href": "#" }
              },
              "children": [

              ],
              "state" : "closed"
            },

              {
              "attr" : {"id" : "node-2"},
              "data" : {
                "title" : "Node-2",
                "attr" : {"id" : "node-2" ,"href": "#" }
              },
              "children": [

              ],
              "state" : "closed"
            },

              {
              "attr" : {"id" : "node-3"},
              "data" : {
                "title" : "Node-3",
                "attr" : {"id" : "node-3" ,"href": "#" }
              },
              "children": [

              ],
              "state" : "closed"
            },

              {
              "attr" : {"id" : "node-4"},
              "data" : {
                "title" : "Node-4",
                "attr" : {"id" : "node-4" ,"href": "#" }
              },
              "children": [

              ],
              "state" : "closed"
            },

              {
              "attr" : {"id" : "node-5"},
              "data" : {
                "title" : "Node-5",
                "attr" : {"id" : "node-5" ,"href": "#" }
              },
              "children": [

              ],
              "state" : "closed"
            }
     ],
     // the method where the ajax request will be sent to get thejson data to build the tree
    "ajax" : {
      "url" : "/my_url/tree",
      "data" : function (focus_element) {
        return { node : focus_element.attr ? focus_element.attr("id") : 0 };
      }
    }
  },

  "themes" : {
    "theme" : "classic",
    "dots" : true,
    "icons" : true
  },
  "plugins" : ["themes",  "json_data" ,"ui"]

})

页面上有一个准备好另一个jquery文档功能将点击锚节点创建但上面的jstree

$(document).ready(function() {

 $("a#node-1").click()     

})

现在问题来了,当页面加载时,树全部被构建 树已构建,但 node-1 锚链接没有被点击。

调试它我发现 console.log 总是向我显示 a#node-1 的空数组,这很奇怪。

我在第二个 document.ready 函数中放了 alert 框 以查看在我请求节点时是否构建了树。像这样

$(document).ready(function() {

alert("JSTREE SHOULD BE CREATED BY NOW");

$("a#node-1").click()  

})

但令我惊讶的是,当 警报弹出时,JSTREE 仍在构建树。

通过对 javascript 的一些了解,我知道页面上的脚本标签本质上是同步的,即页面上的第二个脚本仅在第一个执行时执行

这让我相信 JSTREE 是异步运行的。如果是,请任何人分享一些关于它的信息。

顺便说一句,我设法使用 jstree 负载处理程序

实现了同样的目的

$("#someid").bind("loaded.jstree",

   function() {   
       $("a#node-1").click();   
       })

【问题讨论】:

    标签: javascript jstree


    【解决方案1】:

    您的问题有一个有趣的答案:我刚刚发现 jquery.jstree.js (jsTree 1.0-rc3) 中的代码使用 setTimer(...) 来调用 .init()在节点上,即是异步的。我在其他项目中也使用了jsTree 1.0-rc1,它是同步的。

    恐怕您不会发现这是一个实现细节:它取决于您使用的版本。

    按照其他人的建议,使用jstree中的事件机制来实现你想要的。 另一方面,Jurgen 对 DOM 的结构是正确的。

    (*)我通过Github浏览了原始代码,似乎是在2011年发生了变化。在此之前你有:

    jsTree 1.0-rc1 https://github.com/vakata/jstree/blob/0b8ebb2ba468b4c81e3c7645a9335584ddab41f5/jquery.jstree.js

    line 59: instances[instance_id]._init();
    

    而现在,

    jStree 1.0-rc3 https://github.com/vakata/jstree/blob/v.pre1.0/jquery.jstree.js

    line 162: setTimeout(function() { instances[instance_id].init(); }, 0);
    

    【讨论】:

    • 感谢 Caya,你知道了,我相信 jstree 正在“异步”执行是正确的(该死的,如果它会同步执行,它注定会毁掉我所拥有的所有知识)感谢@caya 接受答案并奖励赏金
    【解决方案2】:

    通过阅读 JSTree 文档,我发现了一个有趣的注释: 在第一个代码部分的 http://www.jstree.com/documentation/json_data 页上指出

    // `state` and `children` are only used for NON-leaf nodes
    

    但是您试图将它们用作具有子节点的节点。也许这会导致您的问题。

    【讨论】:

    • No Brother 上面包含“state”和“children”选项的节点是“non-leafy”节点(它们有与其关联的子节点(顺便说一下,没有使用 ajax 加载)),我为了减少代码和清洁度,特意从上面的代码中去掉。
    • 这可能会有所帮助。你也可以尝试把 $("a#node-1").click();在 jsTree 初始化的同一个 $(document).ready 函数中并检查您的错误是否继续重现。
    • 谢谢@CoolEsh,但我试过了,因此我粘贴了代码,以便您可以全面了解相同的概念
    【解决方案3】:

    编辑。刚查了一下文档,我的第一个猜测是正确的,其余的都删除了。

    ID 将应用于包含<a><li>。做

    $("li#node-1 > a").click()
    

    相反。你的 CSS 选择器是错误的,永远不会匹配,这与异步树行为无关。

    编辑:

    现在,如果您的树是异步构建的,并且您需要等待其加载的事件,您可以使用以下命令执行此操作 代码初始化树之前,或者由于计时竞争条件,您可能会丢失加载的事件:

    jQuery("#someid").bind("loaded.jstree", function (event, data) {
        $("li#node-1 > a").click();
        # or:
        $(this).jstree("open_node", "node-1");
    });
    

    如果您只想让节点在加载时打开,而不是做任何复杂的事情 否则,您也可以使用initial_open init 参数来设置初始打开的节点 完全不用摆弄事件。

    【讨论】:

    • 不,那也没用,是的 CSS 选择器永远不会找到 node-1 锚标记(因为我注意到第二个 document.ready 在第一个 document.ready 仍在构建时执行“jstree”),这是一个问题,当第一个 document.ready 作为页面上的脚本处理时,第二个 document.ready 是如何执行的,表现出同步性质。任何方式粘贴代码以更好地理解相同。
    • 编辑:解释了异步代码初始化所需事件注册的顺序/时间。