js新手试图通过ajax混淆来理解dom(概念)

时间:2015-10-22 07:11:49

标签: javascript jquery ajax dom

我是一个python /数据家伙,在一点点网络上徘徊,从根本上对JS和dom以及所有这些都毫无头绪。所以发生了一些非常奇怪的事情,即使我找到了解决方案,我也在努力理解其原因。

场景:常见问题

有一百万个先前的SO问题沿着“我有一些工作jQuery / JS操纵一些HTML。然后我不是硬编码相关的HTML,而是在其他地方以编程方式创建它并将其拖入其中AJAX。突然间,一切都破了。“

总是,答案是这样的:“你不能那样做。把你的代码连接到亲子链上的某些东西,事件委托是一件神奇的事情,它会拯救你。”

所以这发生在我身上,我花了一个小时左右阅读之前的SO并了解事件授权,事实上,它救了我,我的代码也运行了。

但我不明白为什么它首先被打破了。所以我希望有人可以向我解释基础理论,这样我就会更深入地了解整个dom位。

一些破碎的代码

$(document).ready(function(){

$("#autopubs").load("pubslist.html");
// Obviously, the stuff in pubslist.html is what the next line was 
// supposed to work on
$('.collapse').on('show.bs.collapse', function () {
    $('.collapse.in').collapse('hide');
});
});

解决方案可能并不令人意外。将autopubs包装在一个外部div中并将崩溃事物挂钩。完成,工作,非常不满意。

但我仍然不明白为什么这是必要的。这是破碎的代码应该做的心理模型。

  1. 好的,文档已完成加载!让我们执行我们的代码!
  2. 第一行:让我们去获取这个文件并将其添加到DOM中。这就是世界上的 state,,现在我们要改变它,就像对状态一样。
  3. 好的,现在它是DOM的一部分。我们完成了那条线。我们走到下一行。
  4. 好的,现在我们想要通过类崩溃将一堆事件监听器连接到一切。很酷,让我们来看看DOM的现状。嘿看,那里有崩溃类的所有这些东西。巴姆。迷上了。
  5. 除了4从未发生过,因为第二行代码显然无法看到第一行添加的所有内容。

    直观地说,有两个合理的理由:

    1. 在第一行完成获取文件之前执行的第二行。如果这是真的,那么我已经学到了一些关于javascript(或jquery,或ajax等)的重要内容:行并不总是执行按顺序,或者至少在下一个开始之前不要总是完成。

    2. 第一行实际上并没有改变任何状态。 DOM不是状态。这是别的东西,某种东西......甚至可能是不变的?第一行完全用其他东西修补,第二行无法触及,因为它试图修改DOM。

    3. 老实说,这两种可能性对我来说都很奇怪。但显然我从根本上不理解这里的内容。有人能帮助我吗?

6 个答案:

答案 0 :(得分:4)

JavaScript大量使用异步行为。线条在同一个函数内按顺序执行,但这并不意味着它们完成了#34;他们的行动。

如果您查看loadhttp://api.jquery.com/load/)的文档,可以看到它需要一个可选的complete参数。这是一个回调。它是一个在操作完成时运行的函数。调用load本身只会使加载开始,在背景中排序""。

所以你可以这样做:

$(document).ready(function(){

    $("#autopubs").load("pubslist.html", function() {
        $('.collapse').on('show.bs.collapse', function () {
            $('.collapse.in').collapse('hide');
        });
    });
});

加载回调在完成后运行。

为什么您的原始黑客解决方案确实有效?它将事件处理程序附加到现有的外部div,并在加载时将加载的HTML放入内部。

答案 1 :(得分:2)

你的第一个假设是正确的。当调用ajax时,它的异步意味着它将在完成时运行回调。在这种情况下,jquery已经调用了一个回调来将内容附加到div,但是在延迟大约100到200ms左右之后就会发生这种情况。

但是其他代码可以立即运行,但由于异步调用尚未完成,因此无法找到任何内容。

在jQuery中,如果你查看load的文档,你会看到(arg1, [arg2], [complete])的内容,其中complete将是一个闭包或回调函数。

如果您将代码包装在该回调函数中而不是在其下面,那么在加载和添加内容之后将执行该代码。

修改

加载load也是jquery中的便捷/速记方法之一。有关更多文档,请查看Ajax

此外,DOM非常可变,执行请求的第一行确实在dom上执行操作。由于它是异步的,它会告诉脚本在等待数据时继续运行,这就是它失败的原因。

希望这有助于升技!你得到了正确的照片:)

答案 2 :(得分:0)

如果我正确理解,您应该只在完整的'上推荐新加载的DOM。打回来。看看这里:

http://api.jquery.com/load/

$( "#result" ).load( "ajax/test.html", function() {
  alert( "Load was performed." );
});

答案 3 :(得分:0)

第一行确实被执行了,它改变了状态。之后,您将事件挂钩到更改,并且每次发生更改时都会调用该事件,但不会针对第一个事件调用,因为它已经在事件被连接之前发生。

答案 4 :(得分:0)

jQuery.load是异步的,这意味着您需要提供在通过回调添加内容后执行的任何代码。您在the documentation page的底部有一个工作示例。

答案 5 :(得分:0)

正如其他人所说,JavaScript在执行以下行之前不会等待完成加载功能。因此,您可以使用load函数的回调参数(或任何其他需要时间的函数,如AJAX或动画)。所以你的第一个假设是正确的。 AJAX(异步JS)是一件大事,你应该深入研究它:)

此外,您仍然可以在您的案例中使用委托:

$(document).on('show.bs.collapse', '.collapse', function () {
    var collapse = $(this); // the individual $('.collapse') element triggering the event
});

这会将show.bs.collapse事件绑定到所有.collapse元素,无论它们是现在存在还是稍后添加。原始选择器是 $(document) 。简单来说就是:

“嘿文档,每当事件show.bs.collapse被选择器'.collapse'的元素触发时,运行以下代码。”

您区分直接和间接事件委派或绑定。在您的示例中,您使用直接绑定,因为您最终选择了所有现有的.collapse元素,然后使用它们执行操作:

$('.collapse').on()

您必须明白,这仅适用于在运行该行时被选中的当前现有元素。这不适用于同一类的动态添加元素。