【发布时间】:2018-12-28 16:52:36
【问题描述】:
我有一个使用 jquery 3.2.1 的 HTML5 应用程序。
在应用程序的一部分 - 一个搜索功能 - 我提出了一个 ajax 请求。 ajax 请求的响应是 HTML,其中包括一个 <script> 标记,该标记链接到与应用程序位于同一服务器上的 js 文件。
因此 ajax 代码如下所示 - 用于发出 ajax 请求并将响应写入 ID 为 #ajaxContent 的 div:
$.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;
}
}
});
如果我检查 #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')+'">');
}
});
});
关于提供的赏金的说明:
我提供了赏金,因为这不是一个需要解决的小问题 - 没有人给出可行的答案这一事实证明了这一点。我希望得到正确答案:
- 可使用 jsfiddle 或同等工具进行演示。
- 解释其工作原理/原因。
- 了解ajax响应是HTML和js。 js 作用于响应中的 HTML 元素。因此 both HTML 和 js 需要包含在响应中 - 而不是说“只需将 js 添加到全局文件”(我不希望 js 是全局的,因为它是特定的到给定的 HTML 响应,并且可以在应用程序的不同部分有所不同)。
- 不应使用超时(
setTimeout或其他)。如果用户与 UI 元素交互 - 例如按钮 - 在 HTML 响应中返回 before 超时,因此 js 被触发......这只会导致我们现在遇到的同样问题。因此,就我而言,这不是一个有效的解决方案。 - 如果此问题在 HTML5/jquery 中无法解决,请解释原因并提出其他处理方法。
jsfiddle 显示通过 ajax 返回的 HTML 和 script 标签:
有几个人要求提供小提琴或演示。没有两个人会得到相同的结果——这正是问题的重点——所以我最初没有做一个。返回的写入#ajaxContent 的 HTML 如下所示:http://jsfiddle.net/v4t9j32g/1/ - 这是浏览器中的开发工具在 ajax 响应之后显示的内容。请注意,返回内容的长度可能会有所不同,因为它是对关键字搜索工具的响应,会带回大量过滤器按钮。另请注意,此 HTML 响应包含行 <script src="/js/search_regulations.js"></script>。 这就是有问题的 js 所在的位置,并且上面显示了这个问题的全部内容 - 包含 console.log('search_regulations.js firing') 的位
【问题讨论】:
-
尝试加入 'defer' -
<script defer src=.... -
正如 wazz 所说,这很可能是您的新元素尚未安装到 DOM 的竞争条件。在该脚本中记录选择器的结果,当它不起作用时,您可能会看到找不到它们。 PS 返回 HTML 甚至更糟糕的是 ajax 响应中的脚本非常老派并且不受欢迎,最好返回原始 JSON 数据并按照您的喜好呈现。
-
@DominicTobias 谢谢。我提供赏金的原因是因为我需要一个完整的示例来详细解释所有这些概念。特别是返回 JSON 并呈现它......这如何帮助克服
<script>标签的问题 - 即使必须将响应从 JSON 转换为 HTML,仍然需要 js,所以不确定这有什么帮助?跨度> -
有什么方法可以创建一个发生这种情况的工作示例? @安迪
-
您可以通过将 search_regulations.js 所做的更改包装在 SetTimeout 方法中来证明它是否是竞争条件。将其设置为延迟 5000 毫秒。如果这使事情每次都能完美运行。然后你肯定知道这是一个竞争条件。
标签: javascript jquery html ajax