执行ajax响应中返回的js文件

And*_*ndy 16 html javascript ajax jquery

我有一个使用jquery 3.2.1的HTML5应用程序.

在应用程序的一部分 - 搜索功能 - 我发出ajax请求.来自ajax请求的响应是HTML,这包括一个<script>链接到js文件的标记,该文件与应用程序位于同一服务器上.

所以ajax代码看起来像这样 - 用于发出ajax请求并将响应写入具有ID的div #ajaxContent:

$.ajax({
    url: $('#searchRegulations').attr('action'),
    type: 'post',
    cache: false,
    data: $('#searchRegulations').serialize()
 }).done(function (response, status, xhr) {
        if (response) {
            $('main .content').hide();
            $('#ajaxContent').html(response).show();
            return false;
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

如果我检查#ajaxContent我可以看到<script>标签包含在ajax响应中:

在此输入图像描述

我还检查了我的网络选项卡,以确保/js/search_regulations.js正确加载,它给出了200响应:

里面search_regulations.js有一些jquery切换存在的一些过滤器#ajaxContent.

问题是这个代码似乎只在50%的时间内起作用.当它工作时,它将切换一些过滤器按钮的状态,方法是.active在内部的元素中 添加/删除一个类.browse-ctp__filters-data,然后将它们写入带有ID的隐藏表单#tmpFilters.

为了确保脚本"触发",我放入了该行,console.log('search_regulations.js firing');并确定每次都会在控制台中显示,无论脚本是否起作用.

更奇怪的是,如果在将ajax响应写入页面后将代码剪切/粘贴到我的控制台中,它总是按预期工作.

这是脚本进入页面的方式有问题吗?

我已粘贴下面的脚本,但我不认为这是代码中的代码问题,而是处理浏览器/ ajax响应的方式:

$(function() {  

console.log('search_regulations.js firing');

/* toggle the active (applied) state on browse by filters */
/* @link https://stackoverflow.com/questions/48662677/switch-active-class-between-groups-of-include-exclude-buttons */
$(document).on('click', '.browse-ctp__filters-data .include, .exclude', function(){

    var $this = $(this);

    // Split name into array (e.g. "find_355" == ["find", "355"]) 
    var arr = $this.attr('name').split('_');


    // Toggle active class
    $this.toggleClass("active");
    if ($this.siblings().hasClass("active")) {
      $this.siblings().removeClass("active")
    }

    // Remove any existing instances of the filter from hidden form
    $('#tmpFilters input[value="exclude_'+arr[1]+'"]').remove();
    $('#tmpFilters input[value="find_'+arr[1]+'"]').remove();

    // If a filter has been applied then add it to hidden form
    if ($this.hasClass('active')) {
        $('#tmpFilters').append('<input type="hidden" name="tmpFilter[]" value="'+$this.attr('name')+'">');
    }
});    
}); 
Run Code Online (Sandbox Code Playgroud)

关于赏金的说明:

我提供了赏金,因为这不是一个需要解决的微不足道的问题 - 事实证明,没有人给出可行的答案.我期待正确答案:

  1. 可以用jsfiddle或同等程度来证明.
  2. 解释它是如何/为何起作用的.
  3. 理解ajax响应是HTML和js.js作用于响应中的HTML元素.因此两者的HTML和JS需要被包含在响应-而不是说"只是JS添加到全局文件"(我不想让JS是全球性的,因为它是专门针对给定的HTML响应,并可以在应用的不同部分有所不同).
  4. 不应该使用超时(setTimeout或其他).如果用户与超时之前在HTML响应中返回的UI元素(如按钮)进行交互,因此会触发js ...这只会导致我们现在遇到的同样问题.因此,就我而言,这不是一个有效的解决方案.
  5. 如果在HTML5/jquery中无法解决这个问题,请解释原因,并建议任何其他方法来处理它.

jsfiddle显示通过ajax返回的HTML和脚本标记:

有几个人要求小提琴或演示.没有2人会得到相同的结果 - 这是问题的重点 - 所以我最初没有制作一个.写入的HTML返回#ajaxContent如下所示:http://jsfiddle.net/v4t9j32g/1/ - 这是浏览器中的dev工具在ajax响应后显示的内容.请注意,返回的内容的长度可能会有所不同,因为它是对关键字搜索工具的响应,它会带回一大堆过滤器按钮.另请注意,此HTML响应包含该行<script src="/js/search_regulations.js"></script>.这就是有问题的js所在的位置,其中的全部内容显示在此问题的上方 - 包含的位console.log('search_regulations.js firing')

bas*_*gio 6

我看到的问题之一是您多次将 绑定onclick相同的元素......

由于 js 可以通过 ajax 请求多次加载,因此在再次附加事件之前首先分离很重要。

另一个问题是,您在$(document).ready事件中运行代码(即加载 HTML 文档并且 DOM 准备就绪时),但是您最好在$(window).load事件中运行代码(执行稍晚一点) ,当整个页面完全加载时,包括所有框架、对象和图像)

示例

$(window).load(function() {  

    console.log('search_regulations.js firing');

    //off: detach the events
    //on: attach the events
    $('.browse-ctp__filters-data .include, .exclude').off('click').on('click', function(){
        ...
    }
}); 
Run Code Online (Sandbox Code Playgroud)

  • 我同意你的第一点。如果代码加载了偶数次,`toggle` 将自己反转,看起来什么也没发生。`.load` 部分应该无关紧要,因为所有这些都是在 ajax 调用之后完成的,并且元素是否存在并不重要(事件处理程序被附加到文档,而不是 dom 元素)。不过有一个修改:不是调用`.off('click')`(这可能会删除其他点击处理程序),事件应该被赋予一个命名空间,以便保存以删除。`).off('click.toggleActive').on('click.toggleActive', ...)` (2认同)