Pavel Mayorov Asked:2020-02-10 14:34:17 +0800 CST2020-02-10 14:34:17 +0800 CST 2020-02-10 14:34:17 +0800 CST 如何使用具有动态内容的 jquery 插件或为什么 javascript 在 AJAX 之后下降 772 我将几个超级插件连接到页面: $("*[data-foo]").foo(); $(".bar").bar(); $("p a b i").baz(); 但是通过 AJAX 加载后,代码停止工作!怎么解决?! javascript 1 个回答 Voted Best Answer Pavel Mayorov 2020-02-10T14:34:17+08:002020-02-10T14:34:17+08:00 说“代码停止工作”是不正确的。因为代码没有开始工作。当你写的时候$(селектор).метод()——这意味着一个单一的方法调用。此方法适用于当前页面上与传递的选择器匹配的所有元素。 通常他们说为了修复错误,通过ajax刷新页面后,再次执行代码。但这并不总是正确的。 重新执行视图$(".bar").bar();调用bar不仅会在新元素上调用插件,还会在旧元素上调用插件。充其量,这将是浪费时间。但在最坏的情况下,由于重复调用,某些东西会损坏(如果您订阅了事件,那么某些东西肯定会损坏!)。因此,您只需将插件应用于更新的容器。 还有一个关于如何在更新后调用这些插件的问题。通常他们会尝试通过服务器响应中的内联脚本来执行此操作——但在这种情况下,该脚本无法访问正在更新的元素。有必要查看更新本身发生的代码 - 并在那里进行编辑。 以上是一般原则。下面我将编写一种方法,您可以尝试使代码在一个简单的案例中工作。 我们将页面的所有“改进”收集在一个地方: applyPlugins(); // ... function applyPlugins() { $("*[data-foo]").foo(); $(".bar").bar(); $("p a b i").baz(); } 我们更改结果函数,使其仅在传递给它的容器内起作用: applyPlugins($(document)); function applyPlugins($cnt) { $cnt.find("*[data-foo]").foo(); $cnt.find(".bar").bar(); $cnt.find("p a b i").baz(); } 这里我们使用了find查找子元素的方法。 重要的!函数applyPlugins不得访问传递给它的容器之外的元素$cnt! 我们在代码中找到执行动态内容更新或元素创建的那些地方。 这可能是一个电话.html(...): $.ajax({ // ... success: function (data) { $("#some_block").html(data); } }); 在这种情况下,您需要在html调用之后添加一个调用applyPlugins: $.ajax({ // ... success: function (data) { applyPlugins($("#some_block").html(data)); } }); 这可能是一个电话.load(): $("#some_block").load("http://some/url"); 在这种情况下,您需要在那里添加一个带有回调函数的参数: $("#some_block").load("http://some/url", function () { applyPlugins($(this)); }); 它也可能是别的东西。但我仍然希望你能找到这个地方——这是你的代码,而不是别人的:) 如果用于插件的选择器通过动态容器,上述方法将不起作用: $(".foo .bar .baz").somePlugin(); $(".bar").load(...); 在这种情况下,尝试直接覆盖视图中的 applyPlugins$cnt.find(".foo .bar .baz").somePlugin()将失败,因为容器.foo的.bar子容器都没有被更新。 在这种情况下,您可能应该更加注意更新或加载的内容和方式,而不是盲目地使用 applyPlugins 技巧。 或者你可以尝试做这样的事情来为所有情况提供 - 但这段代码将很难理解和调试: $cnt.find(".foo .bar .baz").somePlugin(); $cnt.filter(".foo, .foo *").find(".bar .baz").somePlugin(); $cnt.filter(".foo .bar, .foo .bar *").find(".baz").somePlugin(); (这会检查当前容器是一个元素.foo还是它的子元素,如果是,则.foo .bar .baz跳过路径中的第一个元素。此代码假定一个元素.foo不能嵌套在另一个元素中。与 相同.bar。) PS 虽然我只谈到了插件,但答案也适用于事件订阅。但这不是最好的方法——因为有更简单的方法。大多数事件都是弹出式的 - 因此它们可以在文档根目录中捕获。并且 jQuery 具有用于过滤弹出事件的内置机制。例子: $(document).on("click", "a[data-href]", function (e) { // ... }) 此处理程序将监听对具有属性集的任何链接的点击,data-href而不管它们以何种方式或何时出现在页面上。
说“代码停止工作”是不正确的。因为代码没有开始工作。当你写的时候
$(селектор).метод()
——这意味着一个单一的方法调用。此方法适用于当前页面上与传递的选择器匹配的所有元素。通常他们说为了修复错误,通过ajax刷新页面后,再次执行代码。但这并不总是正确的。
重新执行视图
$(".bar").bar();
调用bar
不仅会在新元素上调用插件,还会在旧元素上调用插件。充其量,这将是浪费时间。但在最坏的情况下,由于重复调用,某些东西会损坏(如果您订阅了事件,那么某些东西肯定会损坏!)。因此,您只需将插件应用于更新的容器。还有一个关于如何在更新后调用这些插件的问题。通常他们会尝试通过服务器响应中的内联脚本来执行此操作——但在这种情况下,该脚本无法访问正在更新的元素。有必要查看更新本身发生的代码 - 并在那里进行编辑。
以上是一般原则。下面我将编写一种方法,您可以尝试使代码在一个简单的案例中工作。
我们将页面的所有“改进”收集在一个地方:
我们更改结果函数,使其仅在传递给它的容器内起作用:
这里我们使用了
find
查找子元素的方法。重要的!函数
applyPlugins
不得访问传递给它的容器之外的元素$cnt
!我们在代码中找到执行动态内容更新或元素创建的那些地方。
这可能是一个电话
.html(...)
:在这种情况下,您需要在
html
调用之后添加一个调用applyPlugins
:这可能是一个电话
.load()
:在这种情况下,您需要在那里添加一个带有回调函数的参数:
它也可能是别的东西。但我仍然希望你能找到这个地方——这是你的代码,而不是别人的:)
如果用于插件的选择器通过动态容器,上述方法将不起作用:
在这种情况下,尝试直接覆盖视图中的 applyPlugins
$cnt.find(".foo .bar .baz").somePlugin()
将失败,因为容器.foo
的.bar
子容器都没有被更新。在这种情况下,您可能应该更加注意更新或加载的内容和方式,而不是盲目地使用 applyPlugins 技巧。
或者你可以尝试做这样的事情来为所有情况提供 - 但这段代码将很难理解和调试:
(这会检查当前容器是一个元素
.foo
还是它的子元素,如果是,则.foo .bar .baz
跳过路径中的第一个元素。此代码假定一个元素.foo
不能嵌套在另一个元素中。与 相同.bar
。)PS 虽然我只谈到了插件,但答案也适用于事件订阅。但这不是最好的方法——因为有更简单的方法。大多数事件都是弹出式的 - 因此它们可以在文档根目录中捕获。并且 jQuery 具有用于过滤弹出事件的内置机制。例子:
此处理程序将监听对具有属性集的任何链接的点击,
data-href
而不管它们以何种方式或何时出现在页面上。