如何销毁Bootstrap Popover的所有实例

How do I destroy all instances of Bootstrap Popover?

本文关键字:实例 Popover 何销毁 Bootstrap      更新时间:2023-09-26

我有一个使用Backbone的单页应用程序,每当我浏览某个内容,然后单击"返回"按钮时,弹出窗口就会永远保留。

我想在加载新实例时销毁popover的所有实例。

找到通过数据API创建的弹出窗口并不困难,其他答案也涵盖了这一点,如David Mulder和Amir Popovich的答案。你只需要:

$("[data-toggle='popover']").popover('hide');

或者,如果您需要或喜欢,也可以使用destroy

挑战在于处理那些动态创建的弹出窗口

用弹出框标记元素

我会实现这样的东西。我会覆盖默认的popover方法,并尝试尽早执行此覆盖,以便所有需要popover的都使用我的覆盖。它所做的只是用类标记使用popover的元素。Bootstrap本身不标记它们:

// Override popover so as to mark everything that uses a popover.
var old_popover = $.fn.popover;
function my_popover() {
  this.addClass('marked-as-having-a-popover');
  return old_popover.apply(this, arguments);
}
$.fn.popover = my_popover;

然后,为了在卸载前清除所有内容,我会输入检测卸载的代码如下:

$(".marked-as-having-a-popover").popover('hide');

或者,如果测试表明它更适合您的用例,它可以使用destroy而不是hide

现在,如果覆盖发生得足够早,并且您没有加载多个jQueries的页面,则上面的方法将工作。(是的,这是可能的。)我在一个应用程序中使用了类似的东西来处理工具提示,所以我知道原理是正确的。碰巧在我的应用程序中,所有工具提示都是由我的代码创建的,所以没有丢失东西的风险。

查找具有弹出窗口的所有元素,甚至是未标记的元素

如果您所处的情况是,可以在不标记的情况下创建popover(我称之为"escapee"),那么您需要查询整个DOM并找到哪些元素具有popover。这里没有捷径。您不能依赖像data-content这样的属性,因为popover可以完全动态地创建(即没有任何data-属性)。此外,所有类型的元素都可以得到popover,因此不能可靠地假设只有button元素会有popover。找到所有需要处理的东西的唯一可靠方法是查看DOM中的每个元素,并检查它是否有popover:

// Obviously this is quite expensive but in a situation where there *can* be escapees
// then you have to check all elements to see if they have a popover.
$("*").each(function () {
    // Bootstrap sets a data field with key `bs.popover` on elements that have a popover.
    // Note that there is no corresponding **HTML attribute** on the elements so we cannot
    // perform a search by attribute.
    var popover = $.data(this, "bs.popover");
    if (popover)
        $(this).popover('hide');
});

同样,可以使用destroy而不是hide

概念证明

这是一把小提琴,说明了整个事情:

  • "添加动态Popover"模拟在覆盖生效时添加Popover的代码。

  • "添加Escapee"模拟了添加popover并以某种方式使用原始Bootstrap代码的代码。

  • "清除标记"仅清除标记的弹出窗口。

  • "全部清除"清除所有标记或未标记的弹出窗口。

尝试使用以下方法:

$('YOUR_ELEMENT_SELECTOR').popover('dispose');

引用url:https://getbootstrap.com/docs/4.1/components/popovers/

它非常简单,只需调用一个带有参数"destroy"的函数popover()即可销毁popover。它将销毁由$("[data toggle=popover]")创建的所有popover();

您可以查看文档以了解popover()的更多选项和参数。

我建议您销毁具有特定类名的popover,而不是使用以下代码。

$("[data-toggle='popover']").popover('destroy');

上面的代码将销毁页面中的所有弹出窗口。因此,使用类选择器来代替此操作。

$(".YourClassName").popover('destroy');

如果您有问题,需要删除所有内容:

$('.popover').remove();

将有所帮助(Popover自动添加此类,即使是动态创建的对象)。它破坏了所有popover DOM对象,包括回调等。但这是一条艰难的道路。通常情况下,我会对popover类(干净的方式)感到不快,当然之后我会做一次艰难的清理。对我来说很好!

$('.popover').popover('dispose');
$('.popover').remove();

如果您想删除所有execpt one,请使用filter()和:not Selector

$('.popover').filter(':not(#yourID)').popover('dispose');
$('.popover').filter(':not(#yourID)').remove();

popover还添加了一个带有随机数的id

#popoverxxxxx where xxxxx is a five digit number.

这有时有助于比较popover。当然,这也可以用来识别弹出窗口。

$('[data-toggle="popover"]').popover('hide')

或者更极端的呼叫

$('[data-toggle="popover"]').popover('destroy')

尽管我经常怀疑这是否合理。仍然要解决您遇到的特定bug,您应该创建一个最小的测试用例,以便能够解决该bug本身。

哦,如果你特别想检查打开的弹出窗口,你可以使用.data("bs.popover").$tip.parent().length(这有点像黑客),例如:

$('[data-toggle="popover"]:eq(0)').data("bs.popover").$tip.parent().length == 1

您可以使用以下方法hide所有弹出窗口:

$("[data-toggle='popover']").popover('hide');

您可以使用以下内容destroy所有弹出窗口:

$("[data-toggle='popover']").popover('destroy');

hidedestory之间的区别在于,当hide弹出时,不需要反应,但当破坏时,

查看我的JSFIDDLE,然后:

  • 单击所有弹出窗口,然后单击hide。单击hide后,可以再次单击弹出窗口。

  • 单击所有弹出窗口,然后单击destroy。单击destroy后,再次尝试单击弹出窗口,并查看不会发生任何事情,因为它们被破坏
    为了使它们再次发挥作用,您需要单击反应,然后尝试。

必须手动初始化Popovers,这样您就可以确切地知道要销毁什么,因为您已经初始化了它。您应该使用相同的选择器来调用destroy函数。或者我错过了什么?