【问题标题】:Javascript ajax calls don't work inside of dynamically loaded HTMLJavascript ajax 调用在动态加载的 HTML 中不起作用
【发布时间】:2016-02-20 22:48:10
【问题描述】:

我正在尝试编写一个通用的 javascript 脚本以方便点击 <a href> 链接,同时只替换内部 HTML 而不是重新加载整个页面。奇怪的是,它可以工作,除了新加载的 HTML 内的任何链接。

<script src="{{ asset('bundles/app/js/jquery-2.2.0.min.js') }}"></script>
<script src="{{ asset('bundles/app/js/jquery.menu-aim.js') }}"></script>
<script src="{{ asset('bundles/app/js/main.js') }}"></script>
<script type="text/javascript">

    $(document).ready(function() {
        $("a").on("click", function(){
            event.preventDefault();
            $.ajax({
                'url': $(this).attr('href'),
                type: "post",
                success: function(response, status) {
                    document.getElementById("content").innerHTML = response;
                },
                error: function() {
                    console.log('failure');
                }
            });
        });
    });
</script>

当我将加载的 HTML 中的完全相同的 URL 直接放在包含初始链接的侧边栏菜单中时,它可以正常加载。根据文档, .on 函数应该将自己附加到以后添加的任何元素上。我也按照旧答案的建议尝试了 .delegate 和已弃用的 .live ,但后来连菜单侧边栏都停止工作了。

我在这里错过了什么?

【问题讨论】:

  • 您还需要在新加载的 HTML 上安装点击处理程序。
  • 您需要将 click 事件委托给动态添加的内容,例如 $(parentElement).on("click", "a", function(){...,其中 parentElement 应该是一个不会自行动态加载的元素。您也可以将文档用作 parentElement。
  • 它应该会中断,因为 event 未定义
  • 我的问题不同,因为我不是动态创建元素,而是在另一个已经打开的页面中加载现有页面

标签: javascript jquery html ajax


【解决方案1】:

在这里,我假设您的链接容器是 ID 的“内容”,如果不使用正确的容器 ID 修复它,或者甚至将它们包装在一个中:

$(document).ready(function() {
  $('#content').on('click', 'a', function() {
    event.preventDefault();
    $.ajax({
      'url': $(this).attr('href'),
      type: "post"
    }).done(function(response, status) {
      document.getElementById("content").innerHTML = response;
    }).fail(function() {
      console.log('failure');
    });
  });
});

示例标记:

<div id="content">
    <a href="myurl">clickme</a>
</div>

这是不可取的,(将其放在文档上)将处理程序放在容器上 如果可以的话

$(document).ready(function() {
  $(document).on('click', 'a', function() {
    event.preventDefault();
    $.ajax({
      'url': $(this).attr('href'),
      type: "post"
    }).done(function(response, status) {
      document.getElementById("content").innerHTML = response;
    }).fail(function() {
      console.log('failure');
    });
  });
});

至于为什么这是不可取的(文档);您希望将事件处理程序挂钩放置在尽可能靠近元素的位置;当您像此处一样附加到文档时,如果强制代码遍历整个文档,以便事件处理程序找到 a 链接并查找对这些链接的点击。

注意文档说

“一个选择器字符串,用于过滤触发事件的选定元素的后代。如果选择器为空或省略,则始终在到达选定元素时触发事件。”

因此,对于您的情况,a 选择器。因此,它将事件处理程序放置在文档中的所有内容上,然后为您的 a 选择器过滤。所以如果你把它放在一个更小的容器上,它必须对每个执行的事件(点击)进行更少的过滤。

【讨论】:

  • 为什么这是不可取的?我正在使用带有 Symfony 的 Twig 块,这对我来说都是全新的,这似乎牺牲了可读性以获得我不太了解的一些收益。这会自动附加到新元素吗?我渴望学习,如果您有任何有趣的阅读材料,我会很乐意接受。
  • 为选择过滤器添加了注释
  • 我明白了,这确实很丑。我没有注意到速度上的差异,因为我的页面很小,但这无论如何都是不受欢迎的行为。
【解决方案2】:

您还必须将行为应用到加载的 HTML,就像在这个例子中一样(未测试):

$(document).ready(function() {

    function addBehaviour() {

        // .off first so existing behaviour will be removed and not applied multiple times

        $("a").off("click").on("click", function(){

            event.preventDefault();
            $.ajax({
                'url': $(this).attr('href'),
                type: "post",
                success: function(response, status) {
                    document.getElementById("content").innerHTML = response;
                    addBehaviour(); // add the behaviour
                },
                error: function() {
                    console.log('failure');
                }
            });
        });
    }   

    addBehaviour();


});

【讨论】:

  • 这个解决方案看似简单有效,我笑得很开心。在阅读 jquery 教程时,我已经为此绞尽脑汁了好几个小时,但这只是工作。很好的答案!
  • 虽然这确实解决了我的问题,但我必须把它交给 Mark,因为他严格遵循编码标准并且在查找元素方面更有效。我不赞成它,因为它对理解 JS 如何处理元素非常有帮助。
  • 没问题,很高兴我能帮上忙 :)
猜你喜欢
  • 2022-11-30
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-10
  • 1970-01-01
  • 2016-01-14
相关资源
最近更新 更多