JavaScript/jQuery:如何在“display:none”被移除时触发事件?

4

如果这个问题之前已经被回答了,我很抱歉,我在搜索中找不到。

当4个元素取消隐藏(“display:none”被删除)时,我必须标记它们以触发事件。我认为mutationObserver是正确的方法,但是我无法过滤到我需要的事件。

有人有这方面的经验吗?

编辑:不幸的是,我们没有访问实际取消隐藏元素的脚本。它们由另一个团队拥有和保护。我们唯一可以关注的是元素何时取消隐藏。

我正在尝试弄清楚如何根据我的需求进行编辑。

    // Blocker is the element that has a changing display value
var blocker  = document.querySelector( '#blocker' );
// Trigger changes the display value of blocker
var trigger  = document.querySelector( '#trigger' );
// Our mutation observer, which we attach to blocker later
var observer = new MutationObserver( function( mutations ){
    mutations.forEach( function( mutation ){
        // Was it the style attribute that changed? (Maybe a classname or other attribute change could do this too? You might want to remove the attribute condition) Is display set to 'none'?
        if( mutation.attributeName === 'style' && window.getComputedStyle( blocker ).getPropertyValue( 'display' ) !== 'none'
          ){
            alert( '#blocker\'s style just changed, and its display value is no longer \'none\'' );
        }
    } );
} );

// Attach the mutation observer to blocker, and only when attribute values change
observer.observe( blocker, { attributes: true } );

// Make trigger change the style attribute of blocker
trigger.addEventListener( 'click', function(){
    blocker.removeAttribute( 'style' );
}, false );

在触发display: none移除的任何脚本/行为中触发自定义事件? - David Thomas
很不幸,我们无法访问那个脚本。这是第三方标记公司提供的。 - Nathan Poorbaugh
3个回答

12

开始了

var blocker  = document.querySelector('#blocker');
var previousValue = blocker.style.display;

var observer = new MutationObserver( function(mutations){
    mutations.forEach( function(mutation) {
        if (mutation.attributeName !== 'style') return;
        var currentValue = mutation.target.style.display;
        if (currentValue !== previousValue) {
           if (previousValue === "none" && currentValue !== "none") {
             console.log("display none has just been removed!");
           }

           previousValue = mutation.target.style.display;
        }
    });
});


observer.observe(blocker, { attributes: true });

基本上,我们会获取样式属性中设置的默认值(如果有的话) - 这个值存储在 previousValue 中;然后我们离开这段代码,但是我们在循环中做了一些不同之处。首先,我们检查目标中的样式是否已更改。然后我们获取目标样式属性中的当前显示值。下一步是比较这些值。如果 previousValue 是 "none",现在是其他值,这意味着 display: none 被取消了。但是请注意,它仅监听此特定更改。如果您不需要监听"none",则可以省略它。

您可以在您的代码中使用它 - 我故意没有编写完整的代码,因此请随意在目标上添加事件侦听器。


我通常使用jQuery的.each选择器来将这些元素应用于具有给定类的每个元素。这个答案是否适用于同一类别的多个对象? - Nathan Poorbaugh
如果您想监听多个元素,那么您需要迭代这些元素。您可以将该代码放置在.each函数内,并删除“blocker”变量,在每个出现的位置粘贴.each循环的第二个参数(elem)。就是这样,还值得一提的是,当观察者不再需要时,您可以断开连接 - 只需调用observer.disconnect()即可。 - Jakub Rożek

1
我发现还有另一种可靠的方法来触发事件,当一个元素被 display:none 隐藏或变为可见时。

这基于 ResizeObserver API,应该适用于所有现代浏览器 (https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API)

当一个元素应用了 display:none 的 CSS 规则时,它的所有尺寸都将为零。因此,为了检测其变为可见,我们只需要监视一个在可见时具有非零尺寸的元素。

const block=document.querySelector("#the-block")
const resizewatcher=new ResizeObserver(entries => {
  for (const entry of entries){
    console.log("Element",entry.target, 
      (entry.contentRect.width == 0) ? 
      "is now hidden" : 
      "is now visible"
    )
  }
})
resizewatcher.observe(block)

这实际上是唯一可行的解决方案,当CSS已经通过类设置,但使用例如媒体查询时。元素上没有属性被更改,因此MutationObserver从未被触发。这非常有效! - Qwerty

0

很遗憾,我不确定您如何“删除”display: none,但是如果您碰巧使用jQuery的$.show函数,则可以指定一个“回调”函数,该函数将在显示“动画”完成后调用。

这里是一个例子:

$(".myElement").show(400, function() {
    // Do something...
});

再次强调,我不确定你是如何移除 display: none 的,所以这可能完全没有帮助。


很遗憾,我们没有那个脚本的所有权,也无法使用它。我们正在与营销人员合作,丰富所收集的数据。 - Nathan Poorbaugh
明白了。请忽略我的回答,因为它没有任何用处,抱歉! - Brynden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接