jQuery当元素可见时

52

基本上,我想知道是否有一种方法可以在元素变为隐藏或可见时自动运行函数,而不是在用户单击上自动运行另一个脚本。

我不希望这只运行一次,因为元素(例如滑块)不断地从可见变为隐藏。

jQuery能否使用bind来绑定元素的可见性到函数中(我不知道如何编写此代码)?

如果需要我更详细地解释我正在尝试做什么,请让我知道。谢谢

伪代码:

$('#element').bind('display:none', function);
function(){
    //do something when element is display:none
}

$('#element').bind('display:block', function2);
function2(){
    //do opposite of function
}

1
如果您自己进行隐藏或可见性操作,可以在其后添加它。 - Hadash
哪个“事件”可以改变元素的可见性? - Dom
这是一个滑块,因此有一个脚本可以自动更改幻灯片。 - sl133
1
可能是Jquery -- Action fires on any event的重复问题,或者至少也要获取滑块监听的事件。 - mplungjan
1
这个回答解决了你的问题吗?如何在滚动后检查元素是否可见? - alev
显示剩余4条评论
6个回答

29

在jQuery中没有用于检测CSS更改的事件。
请参考这里:jQuery中的onHide()类型事件

但是有可能实现:

DOM L2 Events模块定义了突变事件;其中之一 - DOMAttrModified就是你需要的。尽管如此,这些事件不被广泛使用,但至少在Gecko和Opera浏览器中得到支持
来源:使用Jquery检测CSS属性更改的事件

如果没有事件,则可以使用setInterval函数,像这样:

var maxTime = 5000, // 5 seconds
    startTime = Date.now();

var interval = setInterval(function () {
        if ($('#element').is(':visible')) {
            // visible, do something
            clearInterval(interval);
        } else {
            // still hidden
            if (Date.now() - startTime > maxTime) {
                // hidden even after 'maxTime'. stop checking.
                clearInterval(interval);
            }
        }
    },
    100 // 0.1 second (wait time between checks)
);
请注意,使用setInterval来保持监视可能会影响页面的性能。 2018年7月7日:
由于此答案最近获得了一些关注和赞,因此在检测 CSS 更改方面,这里提供额外的更新:
现在,突变事件已被性能更友好的突变观察器所取代。

MutationObserver接口提供了监视对DOM树所做更改的能力。它被设计为DOM3事件规范中旧Mutation Events功能的替代品。

参考:https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

1
这是可行的,所以我不明白为什么那个点踩者不能评论一下他的投票原因——比如说也许监控事物并不是一个好主意,但如果这是我们能做的唯一选择,那么这就是一个解决方案。 - mplungjan
好的,它可以使用选择器:hidden,但我认为它只加载一次。你能看到我编辑过的OP以查看更改吗? - sl133
是的,我尝试过了,可以看到我的原始帖子。我不知道为什么它似乎只运行一次。 - sl133
1
我认为布尔值是用来判断你是否从可见状态变为隐藏状态,反之亦然。 - mplungjan
1
@tariq:感谢提供信息。我已更新我的答案。 - Ganesh Jadhav
显示剩余3条评论

19
(function() {
    var ev = new $.Event('display'),
        orig = $.fn.css;
    $.fn.css = function() {
        orig.apply(this, arguments);
        $(this).trigger(ev);
    }
})();

$('#element').bind('display', function(e) {
    alert("display has changed to :" + $(this).attr('style') );
});

$('#element').css("display", "none")// i change the style in this line !!
$('#element').css("display", "block")// i change the style in this line !!

http://fiddle.jshell.net/prollygeek/gM8J2/3/

更改将被警报。


1
你能解释一下它的作用吗?我不太明白它如何与display:block和display:none一起工作。 - sl133
你可以检查编辑,它会在你更改显示或任何样式时发出警报!! - ProllyGeek
6
避免使用setInterval得到了+1的好评。这是对一个好问题的很好的解决方案。 - joews
1
虽然这可能并没有直接回答问题,但它非常酷和聪明。:) 我刚刚学到了两个关于jQuery的新东西。 - DanielM
1
我的意思是,当媒体查询生效并隐藏或显示页面上的元素时,警报不会触发。我刚刚亲自测试过了。 :) - Sam
显示剩余5条评论

4

我在火狐浏览器上试过了,这个链接http://jsfiddle.net/Tm26Q/1/有效。

$(function(){
 /** Just to mimic a blinking box on the page**/
  setInterval(function(){$("div#box").hide();},2001);
  setInterval(function(){$("div#box").show();},1000);
 /**/
});

$("div#box").on("DOMAttrModified",
function(){if($(this).is(":visible"))console.log("visible");});

更新

目前,突变事件(例如上述解决方案中使用的DOMAttrModified)已被MutationObserver所取代,您可以使用它来检测DOM节点的更改,就像上面的情况一样。


@sl133,因此我在回答中提到了Firefox ^_^,不适用于WebKit浏览器。 - user2587132
我意识到在我实现它之后。它在Firefox上完美运行,可惜在Webkit上不起作用。 - sl133

2

我刚刚改进了ProllyGeek的答案。

有人可能会觉得有用。当在元素上调用.show().hide().toggle()时,您可以访问displayChanged(event, state)事件。

(function() {
  var eventDisplay = new $.Event('displayChanged'),
    origShow = $.fn.show,
    origHide = $.fn.hide;
  //
  $.fn.show = function() {
    origShow.apply(this, arguments);
    $(this).trigger(eventDisplay,['show']);
  };
  //
  $.fn.hide = function() {
    origHide.apply(this, arguments);
    $(this).trigger(eventDisplay,['hide']);
  };
  //
})();

$('#header').on('displayChanged', function(e,state) {
      console.log(state);
});

$('#header').toggle(); // .show() .hide() supported

1

这是一个包含扩展核心方法的jQuery自定义事件,它可以作为一个万能事件,正如在这个帖子中不同人所建议的那样:

(function() {
    var ev = new $.Event('event.css.jquery'),
        css = $.fn.css,
        show = $.fn.show,
        hide = $.fn.hide;

    // extends css()
    $.fn.css = function() {
        css.apply(this, arguments);
        $(this).trigger(ev);
    };

    // extends show()
    $.fn.show = function() {
        show.apply(this, arguments);
        $(this).trigger(ev);
    };

    // extends hide()
    $.fn.hide = function() {
        hide.apply(this, arguments);
        $(this).trigger(ev);
    };
})();

一个外部库,使用类似于$('selector').css('property', value)的东西。

由于我们不想更改库的代码,但是我们确实想要扩展它的行为,所以我们会做如下操作:

$('#element').on('event.css.jquery', function(e) {
    // ...more code here...
});

例子:用户点击由库构建的面板。库根据用户交互显示/隐藏元素。我们想要添加一个传感器,显示由于该交互而隐藏/显示了某些内容,并且应在库函数之后调用。

另一个例子:jsfiddle


-1

我喜欢插件https://github.com/hazzik/livequery,它可以不用计时器工作!

简单易用

$('.some:visible').livequery( function(){ ... } );

但是你需要修正一个错误。请替换这一行。

$jQlq.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html', 'prop', 'removeProp');

$jQlq.registerPlugin('show', 'append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html', 'prop', 'removeProp');

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