JqueryのslideDownとかslideToggleでグィングィン何回も開いたり閉じたりしてしまう現象

Jqueryはとても便利ですし、ノンプログラマーでも使える、みたいな売りですが、やっぱり障害に当たるとそれを乗り越える知識と根性はノンプログラマーと言えど必要になってしまいます。
今回ちょっとはまってしまい、どう検索しようか困ってしまったりしたのでキーワード含めてメモしておきます。

本題の、あなたはslideDownとかslideToggleで何回も開いたり閉じたりしてしまう現象に出くわしたことはないでしょうか。
あるいはslideDownとかslideToggleで開閉が止まらない、とかの言い方でしょうか。

ぱっと思いつく解決方法はJqueryが用意してくれているstop()関数ですね。

$(".example").stop().slideToggle();

stop()関数はアニメーションさせるときには必ずと言ってもいいほどつけます。定石ともいえるでしょう。
しかしこんなもんを入れてもどうにもならんこともあります。
私のバカな体験談はresize()が問題でした。。

function example(){
...
$(".exampleClass").slideToggle();
...
}

$(window).resize(function(){
example();
});

としてresize()関数でウィンドウサイズが変わるたびにUIも変化させてレスポンシブに対応しようとしてたわけですよ。
しかし、ボタンを押すと$(".exampleClass")がトグルで開閉してくれるはずなのに、最初の一回だけはうまくいって、その後はグィングィンと開閉しまくったあげく、動かなくなり…あえなく死亡というような結果になってました。
これは、ボタンの開閉自体がウィンドウサイズをresizeしていることになるので、slideToggleが開こうとするたびにresize関数が発火しまくりexample()が呼び出されまくってバブリングしてしまう、という自体になっていたわけです。

ではどうやって回避したもんか、ですよね。

resize内にtoggleが絡まないようにする

・resize時にY方向の変化には反応しない条件分岐を作って、その中にexample()を置く

とかでしょうか。
私の場合は切り離せたので「・resize内にtoggleが絡まないようにする」で事足りましたが、そうでない場合には「resize時にY方向の変化には反応しない条件分岐」を作ってみるといいかもしれません。
「Y方向の変化には反応しない条件分岐」のサンプルコードはそこらへんに落ちているので、探してみて一番あっているものを当ててみてください。

2 Replies to “JqueryのslideDownとかslideToggleでグィングィン何回も開いたり閉じたりしてしまう現象”

  1. 今アコーディオンメニューで苦戦しています。
    PCではslideToggleは上手く行くんですが、スマホだとなぜか開閉を繰り返ししまいます。
    お手数ですが、解決策を教えて頂けませんか?
    よろしくお願いします。

    $(function () {
    var ua = navigator.userAgent;
    if (ua.indexOf(‘iPhone’) > 0 || ua.indexOf(‘iPad’) > 0 || ua.indexOf(‘Android’) > 0 && ua.indexOf(‘Mobile’) > 0) {
    jQuery(‘ul#menu li ul’).hide();
    jQuery(function () {
    $(“li#profile-btn”).on(‘click touchstart’, function () {
    $(“li#profile-btn ul”).slideToggle(300);
    });

    jQuery(function () {
    $(“li#policy-btn”).on(‘click touchend’, function () {

    $(“li#policy-btn ul”).slideToggle(300)
    });
    });

    jQuery(function () {
    $(“main”).on(‘click touchstart’, function () {
    $(“ul#menu ul”).slideUp(300);
    });
    });
    });
    } else {

    jQuery(function () {
    $(“li#profile-btn”).on(‘mouseenter mouseleave’, function () {
    $(“li#profile-btn ul”).slideToggle(300);
    });
    });
    jQuery(function () {
    $(“li#policy-btn”).on(‘mouseenter mouseleave’, function () {
    $(“li#policy-btn ul”).slideToggle(300);
    });
    });
    }
    });

    • ずいぶんと遅れちゃってすみません。コメントいただいていたことに今気が付きました。

      勘ですが、’click touchstart’がダブルで効いちゃっているんじゃないですかね?
      ‘click’か’touchstart’だけにするとか。
      もしくは、
      $(“main”)にonが効いているんですが、”main”の中に”ul#menu ul”があるわけじゃないですよね?

      参考になれば。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA