Thêm hiệu ứng slide vào menu thả xuống bootstrap


80

Tôi đang sử dụng bootstrap và tôi muốn thêm hoạt ảnh vào menu thả xuống. Tôi muốn thêm hoạt ảnh vào nó, trượt xuống và sao lưu khi rời khỏi nó. Làm thế nào tôi có thể làm điều này?

Những điều tôi đã thử:

Thay đổi tệp thả xuống Js như thế này:

Làm cách nào để làm cho menu thả xuống của Bootstrap trượt lên xuống mượt mà?


1
bạn đã bao gồm bootstrap-dropdown.js ở đâu đó chưa? tôi không thấy nó trong tiêu đề .. và awwww những chiếc bánh này. Tôi đói quá!
ablm

Hmm nó boostrap.js bên trong, tôi đã bao gồm nó nhưng nó didnt làm việc vì vậy tôi loại bỏ nó nhưng tôi lại thêm nó và vâng nếu tôi loại bỏ một trong những mini, nó sẽ không làm việc ở tất cả
Bến Beri

EDIT: oh yeah, nó được bao gồm.
ablm

Ừm. Trình đơn thả xuống mặc định không trượt; Trên phiên bản đã sửa đổi (từ các liên kết), có $ el.parent (). SlideToggle (); gọi một hoạt ảnh JQuery.
ablm

Và btw tôi không biết tại sao bạn bao gồm bootstrap 2 lần. bootstrap.min.js là phiên bản rút gọn.
ablm

Câu trả lời:


149

Nếu bạn cập nhật lên Bootstrap 3 (BS3), chúng đã hiển thị rất nhiều sự kiện Javascript rất tốt để gắn kết chức năng mong muốn của bạn vào. Trong BS3, mã này sẽ cung cấp cho tất cả các menu thả xuống của bạn hiệu ứng hoạt ảnh mà bạn đang tìm kiếm:

  // Add slideDown animation to Bootstrap dropdown when expanding.
  $('.dropdown').on('show.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
  });

  // Add slideUp animation to Bootstrap dropdown when collapsing.
  $('.dropdown').on('hide.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
  });

Bạn có thể đọc về các sự kiện BS3 tại đây và cụ thể về các sự kiện thả xuống tại đây .


4
Tôi đang gặp sự cố với phần slideUp của phần này. Khi ở chế độ thu gọn (Chrome), chiều rộng của danh sách thả xuống trở lại chiều rộng như thể được xem ở chế độ toàn màn hình. Trong khi sử dụng FF, nó trượt xuống, nhưng ẩn thay vì trượt lên.
ScubaSteve

3
Tôi cũng thấy vấn đề này, tôi thực sự đã tạo một chủ đề khác hỏi cụ thể về nó ... stackoverflow.com/questions/26267207/… nhưng tôi không biết chính xác cách khắc phục nó. Tôi cảm thấy như lớp Dropdown không đợi quá trình chuyển đổi kết thúc trước khi xử lý hidden.bs.dropdownsự kiện.
Kyle Johnson

3
điều này hoạt động và thực hiện những gì tôi mong muốn, nhưng trên chế độ xem di động, trình đơn thả xuống cho menu con biến mất nhanh chóng và trông có vẻ bị giật - cảm ơn bạn đã chia sẻ!
Bác Iroh

Tôi không thể làm việc này. Tôi tiếp tục gặp lỗi sau: "Uncaught TypeError: $ (...). Find (...). First (...). Stop không phải là một hàm". Tôi không hiểu làm thế nào .stop () không phải là một hàm trừ khi hoạt ảnh bằng cách nào đó vẫn chưa bắt đầu khi sự kiện được kích hoạt? Tôi đang thiếu gì?
John

Xem thêm câu trả lời của Slipoch để biết thêm về bản sửa lỗi di động.
Tashows

71

Ngoài ra, có thể tránh sử dụng JavaScript cho hiệu ứng thả xuống và sử dụng chuyển tiếp CSS3, bằng cách thêm đoạn mã nhỏ này vào kiểu của bạn:

.dropdown .dropdown-menu {
    -webkit-transition: all 0.3s;
    -moz-transition: all 0.3s;
    -ms-transition: all 0.3s;
    -o-transition: all 0.3s;
    transition: all 0.3s;

    max-height: 0;
    display: block;
    overflow: hidden;
    opacity: 0;
}

.dropdown.open .dropdown-menu { /* For Bootstrap 4, use .dropdown.show instead of .dropdown.open */
    max-height: 300px;
    opacity: 1;
}

Vấn đề duy nhất với cách này là bạn nên chỉ định chiều cao tối đa theo cách thủ công. Nếu bạn đặt một giá trị rất lớn, hoạt ảnh của bạn sẽ rất nhanh.

Nó hoạt động giống như một sự quyến rũ nếu bạn biết chiều cao gần đúng của các menu thả xuống của mình, nếu không, bạn vẫn có thể sử dụng javascript để đặt giá trị chiều cao tối đa chính xác.

Đây là ví dụ nhỏ: DEMO


! Có một lỗi nhỏ với phần đệm trong giải pháp này, hãy kiểm tra nhận xét của Jacob Stamm với giải pháp.


2
Giải pháp tốt đẹp, đánh giá cao nó.
Lalit Narayan Mishra

Tôi thích điều này, nhưng tiếc là hoạt ảnh trượt xuống chỉ hoạt động một lần. Nếu tôi đóng menu và mở lại mà không làm mới trang, nó sẽ mở ngay lập tức. Bất cứ ai khác có vấn đề này?
Nathan R

8
Giải pháp tuyệt vời. Thật không may, có một lỗi nhỏ. Mục đầu tiên trong menu thả xuống vẫn có thể nhấp được, ngay cả khi nó được thu gọn. Bạn có thể biết bằng cách di chuột nhẹ bên dưới menu thả xuống được thu gọn. Không phải là vấn đề lớn trong trường hợp này, vì tùy chọn đầu tiên của bạn là văn bản thuần túy. Tuy nhiên, khi đó là một liên kết, đó là một vấn đề. Giải pháp của tôi là làm "hoạt ảnh hóa" khả năng hiển thị, nhưng trì hoãn diễn ra sau khi những thứ khác kết thúc hoạt ảnh. Hãy khám phá: jsfiddle.net/stamminator/kjLe1tfs/1
Jacob Stamm

Cảm ơn vì đã chỉ ra lỗi đó, Jacob. Có vẻ như đây là vấn đề với phần đệm trong danh sách. Nếu bạn không phiền, tôi sẽ thêm giải pháp của bạn để trả lời.
MadisonTrash

1
Người ta cũng có thể thêm pointer-events:nonevào phiên bản thu gọn, sau đó thêm point-events: allvào menu khi nó có.show
Grey Ayer

24

Tôi đang làm điều gì đó như vậy nhưng khi di chuột thay vì nhấp vào .. Đây là mã tôi đang sử dụng, bạn có thể chỉnh sửa nó một chút để nó hoạt động khi nhấp

$('.navbar .dropdown').hover(function() {
  $(this).find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
  $(this).find('.dropdown-menu').first().stop(true, true).delay(100).slideUp()
});

Điều này hoạt động tuyệt vời! Nhưng có cách nào để làm việc với nó khi di chuột thay vì nhấp chuột không?
arefin2k

Đoạn mã tôi đã đăng ở trên là khi di chuột và không phải khi nhấp.
Yohn

Tốt! Cảm ơn.
ilmk

Không làm việc cho tôi. Tôi thêm này theo <script>thẻ nhưng không xảy ra
YaddyVirus

16

Tôi không biết liệu mình có thể thực hiện chủ đề này hay không, nhưng tôi đã tìm ra cách sửa lỗi nhanh chóng cho lỗi trực quan xảy ra khi lớp đang mở bị xóa quá nhanh. Về cơ bản, tất cả những gì cần làm là thêm chức năng OnComplete bên trong sự kiện slideUp và đặt lại tất cả các lớp và thuộc tính đang hoạt động. Đi đến một cái gì đó như thế này:

Đây là kết quả: Ví dụ về Bootply

Javascript / Jquery:

$(function(){
    // ADD SLIDEDOWN ANIMATION TO DROPDOWN //
    $('.dropdown').on('show.bs.dropdown', function(e){
        $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
    });

    // ADD SLIDEUP ANIMATION TO DROPDOWN //
    $('.dropdown').on('hide.bs.dropdown', function(e){
        e.preventDefault();
        $(this).find('.dropdown-menu').first().stop(true, true).slideUp(400, function(){
            //On Complete, we reset all active dropdown classes and attributes
            //This fixes the visual bug associated with the open class being removed too fast
            $('.dropdown').removeClass('show');
            $('.dropdown-menu').removeClass('show');
            $('.dropdown').find('.dropdown-toggle').attr('aria-expanded','false');
        });
    });
});

Bản trình diễn có một menu bị kẹt mở sau khi bạn nhấp vào một vài menu liên tiếp.
SventoryMang

@DOTang vâng, tôi đoán nó không hoàn hảo, do đó việc sửa chữa nhanh chóng, tôi đoán cấu trúc lại một chút sẽ làm cho nó tốt hơn. Hy vọng rằng vào thời điểm Bootstrap4 đi ra, họ sẽ phải cố định nó
IndieRok

11

đây là giải pháp của tôi cho hiệu ứng slide & fade:

   // Add slideup & fadein animation to dropdown
   $('.dropdown').on('show.bs.dropdown', function(e){
      var $dropdown = $(this).find('.dropdown-menu');
      var orig_margin_top = parseInt($dropdown.css('margin-top'));
      $dropdown.css({'margin-top': (orig_margin_top + 10) + 'px', opacity: 0}).animate({'margin-top': orig_margin_top + 'px', opacity: 1}, 300, function(){
         $(this).css({'margin-top':''});
      });
   });
   // Add slidedown & fadeout animation to dropdown
   $('.dropdown').on('hide.bs.dropdown', function(e){
      var $dropdown = $(this).find('.dropdown-menu');
      var orig_margin_top = parseInt($dropdown.css('margin-top'));
      $dropdown.css({'margin-top': orig_margin_top + 'px', opacity: 1, display: 'block'}).animate({'margin-top': (orig_margin_top + 10) + 'px', opacity: 0}, 300, function(){
         $(this).css({'margin-top':'', display:''});
      });
   });

Cảm ơn. Mã của bạn hoạt động hoàn hảo. Tuy nhiên, tôi không hiểu rõ tại sao chúng ta cần có $(this).css({'margin-top':''});@Vedmant
DucCuong

Điều này là để xóa tham số margin-top sau khi hoạt ảnh hoàn tất, trong trường hợp menu thả xuống có một số lề được thêm vào trong các kiểu tùy chỉnh (như trong chủ đề của tôi). Nó phải hoạt động mà không có nó vì nó hoạt ảnh tới orig_margin_top trở lại, nhưng không để thừa các kiểu nội tuyến sau khi hoàn tất hoạt ảnh.
Vedmant

9

Cập nhật 2018 Bootstrap 4

Trong Boostrap 4, .openlớp đã được thay thế bằng .show. Tôi muốn triển khai điều này chỉ bằng cách sử dụng các chuyển đổi CSS mà không cần thêm JS hoặc jQuery ...

.show > .dropdown-menu {
  max-height: 900px;
  visibility: visible;
}

.dropdown-menu {
  display: block;
  max-height: 0;
  visibility: hidden;
  transition: all 0.5s ease-in-out;
  overflow: hidden;
}

Demo: https://www.codeply.com/go/3i8LzYVfMF

Lưu ý: max-heightcó thể được đặt thành bất kỳ giá trị lớn nào đủ để chứa nội dung thả xuống.


Điều này hoạt động hoàn hảo. Đối với tôi, tôi thậm chí không cần chỉ định chiều cao tối đa vì tôi đang cố gắng đạt được hiệu ứng khác bằng cách sử dụng margin-top.
Cá heo tối cao

tôi thích điều này, bạn chỉ cần css mà không cần nhiều mã js ..
aswzen

8

Khi nhấp vào nó có thể được thực hiện bằng cách sử dụng mã dưới đây

$('.dropdown-toggle').click(function() {
  $(this).next('.dropdown-menu').slideToggle(500);
});

Điều này hoạt động tốt nhưng khi bạn mất tiêu điểm, menu thả xuống vẫn mở, điều này không bình thường.
Barry Michael Doyle

7

Tôi đang sử dụng mã ở trên nhưng tôi đã thay đổi hiệu ứng trì hoãn bằng slideToggle.

Nó trượt trình đơn thả xuống khi di chuột với hoạt ảnh.

$('.navbar .dropdown').hover(function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideToggle(400);
    }, function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideToggle(400)
    });

1
không thực sự cần phải xác định nó hai lần. khi sử dụng một chuyển đổi, nó sẽ hoạt động mà không có cái thứ hai.
Dallas

3

Câu trả lời mở rộng, là câu trả lời đầu tiên của tôi, vì vậy xin lỗi nếu không có đủ chi tiết trước đó.

Đối với Bootstrap 3.x Cá nhân tôi thích hoạt ảnh CSS hơn và tôi đã sử dụng animate.css & cùng với Bootstrap Dropdown Javascript Hooks. Mặc dù nó có thể không mang lại hiệu quả chính xác cho bạn nhưng đây là một cách tiếp cận khá linh hoạt.

Bước 1: Thêm animate.css vào trang của bạn bằng các thẻ head:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.4.0/animate.min.css">

Bước 2: Sử dụng HTML Bootstrap tiêu chuẩn trên trình kích hoạt:

<div class="dropdown">
  <button type="button" data-toggle="dropdown">Dropdown trigger</button>

  <ul class="dropdown-menu">
    ...
  </ul>
</div>

Bước 3: Sau đó thêm 2 thuộc tính dữ liệu tùy chỉnh vào phần tử dropdrop-menu; dữ liệu thả xuống cho hoạt ảnh trong và thả xuống dữ liệu cho hoạt ảnh ngoài. Đây có thể là bất kỳ hiệu ứng animate.css nào như fadeIn hoặc fadeOut

<ul class="dropdown-menu" data-dropdown-in="fadeIn" data-dropdown-out="fadeOut">
......
</ul>

Bước 4: Tiếp theo, thêm Javascript sau để đọc các thuộc tính dữ liệu data-dropdown-in / out và phản ứng với các hook / sự kiện của Bootstrap Javascript API ( http://getbootstrap.com/javascript/#dropdowns-events ):

var dropdownSelectors = $('.dropdown, .dropup');

// Custom function to read dropdown data
// =========================
function dropdownEffectData(target) {
  // @todo - page level global?
  var effectInDefault = null,
      effectOutDefault = null;
  var dropdown = $(target),
      dropdownMenu = $('.dropdown-menu', target);
  var parentUl = dropdown.parents('ul.nav'); 

  // If parent is ul.nav allow global effect settings
  if (parentUl.size() > 0) {
    effectInDefault = parentUl.data('dropdown-in') || null;
    effectOutDefault = parentUl.data('dropdown-out') || null;
  }

  return {
    target:       target,
    dropdown:     dropdown,
    dropdownMenu: dropdownMenu,
    effectIn:     dropdownMenu.data('dropdown-in') || effectInDefault,
    effectOut:    dropdownMenu.data('dropdown-out') || effectOutDefault,  
  };
}

// Custom function to start effect (in or out)
// =========================
function dropdownEffectStart(data, effectToStart) {
  if (effectToStart) {
    data.dropdown.addClass('dropdown-animating');
    data.dropdownMenu.addClass('animated');
    data.dropdownMenu.addClass(effectToStart);    
  }
}

// Custom function to read when animation is over
// =========================
function dropdownEffectEnd(data, callbackFunc) {
  var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
  data.dropdown.one(animationEnd, function() {
    data.dropdown.removeClass('dropdown-animating');
    data.dropdownMenu.removeClass('animated');
    data.dropdownMenu.removeClass(data.effectIn);
    data.dropdownMenu.removeClass(data.effectOut);

    // Custom callback option, used to remove open class in out effect
    if(typeof callbackFunc == 'function'){
      callbackFunc();
    }
  });
}

// Bootstrap API hooks
// =========================
dropdownSelectors.on({
  "show.bs.dropdown": function () {
    // On show, start in effect
    var dropdown = dropdownEffectData(this);
    dropdownEffectStart(dropdown, dropdown.effectIn);
  },
  "shown.bs.dropdown": function () {
    // On shown, remove in effect once complete
    var dropdown = dropdownEffectData(this);
    if (dropdown.effectIn && dropdown.effectOut) {
      dropdownEffectEnd(dropdown, function() {}); 
    }
  },  
  "hide.bs.dropdown":  function(e) {
    // On hide, start out effect
    var dropdown = dropdownEffectData(this);
    if (dropdown.effectOut) {
      e.preventDefault();   
      dropdownEffectStart(dropdown, dropdown.effectOut);   
      dropdownEffectEnd(dropdown, function() {
        dropdown.dropdown.removeClass('open');
      }); 
    }    
  }, 
});

Bước 5 (tùy chọn): Nếu bạn muốn tăng tốc hoặc thay đổi hoạt ảnh, bạn có thể làm như vậy với CSS như sau:

.dropdown-menu.animated {
  /* Speed up animations */
  -webkit-animation-duration: 0.55s;
  animation-duration: 0.55s;
  -webkit-animation-timing-function: ease;
  animation-timing-function: ease;
}

Đã viết một bài báo với nhiều chi tiết hơn và tải xuống nếu có ai quan tâm: article: http://bootbites.com/tutorials/bootstrap-dropdown-effects-animatecss

Hy vọng điều đó hữu ích và bài viết thứ hai này có mức độ chi tiết cần thiết Tom


3
Sẽ là tốt nếu ít nhất bao gồm một số chi tiết trong câu trả lời của bạn - chỉ liên kết đến trang web của bạn không thực sự là một câu trả lời hay.
ajshort

@GeraldSchneider đã cập nhật câu trả lời chi tiết hơn. Là câu trả lời đầu tiên của tôi trên stackoverflow vì vậy đánh giá cao phản hồi.
Tom James

2
$('.navbar .dropdown').hover(function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
}, function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
});

Mã này hoạt động nếu bạn muốn hiển thị danh sách thả xuống khi di chuột.

Tôi vừa thay đổi .slideTogglethành .slideDown& .slideUp, và xóa (400)thời gian


1

Đây là một giải pháp đơn giản tuyệt vời sử dụng jQueryhoạt động hiệu quả:

$('.dropdown-toggle').click(function () {
    $(this).next('.dropdown-menu').slideToggle(300);
});

$('.dropdown-toggle').focusout(function () {
    $(this).next('.dropdown-menu').slideUp(300);
})

Chuyển đổi hoạt ảnh slide xảy ra khi nhấp chuột và nó luôn trượt sao lưu khi mất tiêu điểm.

Thay đổi 300giá trị thành bất kỳ thứ gì bạn muốn, số càng thấp thì hoạt ảnh càng nhanh.

Biên tập:

Giải pháp này sẽ chỉ hoạt động đối với chế độ xem trên máy tính để bàn. Nó sẽ cần một số sửa đổi thêm để hiển thị đẹp cho thiết bị di động.


Này không làm việc cho tôi, nhưng sau khi tôi di chuyển chuột lên menu con (tức là xa dropdown-toggle) nó biến mất một lần nữa, có nghĩa là tôi không thể chọn các mục trong menu phụ
Bassie

1

BOOTSTRAP 3 THAM KHẢO

Được thêm vào vì tôi luôn bị giải pháp trong chuỗi này bắt gặp và nó khiến tôi bị nghẹt thở mọi lúc.

Về cơ bản, trình đơn thả xuống của BS ngay lập tức loại bỏ .openlớp khỏi cha mẹ, vì vậy việc trượt lên không hoạt động.

Sử dụng cùng một bit như các giải pháp khác cho slideDown ();

// ADD SLIDEUP ANIMATION TO DROPDOWN //
$('.dropdown').on('hide.bs.dropdown', function(e){
  e.preventDefault();
  $(this).find('.dropdown-menu').first().stop(true, true).slideUp(300, function(){
    $(this).parent().removeClass('open');
  });
});

0

Đối với Bootstrap 3, biến thể này trên các câu trả lời ở trên làm cho slideUp()hoạt ảnh di động mượt mà hơn; các câu trả lời ở trên có hoạt ảnh bị giật vì Bootstrap xóa .openlớp khỏi cha của nút chuyển đổi ngay lập tức, vì vậy mã này khôi phục lớp cho đến khi slideUp()hoạt ảnh kết thúc.

// Add animations to topnav dropdowns
// based on https://stackoverflow.com/a/19339162
// and https://stackoverflow.com/a/52231970

$('.dropdown')
  .on('show.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown(300);
  })
  .on('hide.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, false).slideUp(300, function() {
      $(this).parent().removeClass('open');
    });
  })
  .on('hidden.bs.dropdown', function() {
    $(this).addClass('open');
  });

Sự khác biệt chính:

  • Trong hide.bs.dropdowntrình xử lý sự kiện, tôi đang sử dụng .stop()giá trị mặc định của 's ( false) cho đối số thứ hai của nó ( jumpToEnd)
  • Trình hidden.bs.dropdownxử lý sự kiện khôi phục .openlớp về cha mẹ của nút bật tắt thả xuống và nó thực hiện điều này khá nhiều ngay sau khi lớp được xóa lần đầu tiên. Trong khi đó slideUp()hoạt ảnh vẫn đang chạy và giống như trong các câu trả lời ở trên, lệnh gọi lại "the-animation-is-complete" của nó chịu trách nhiệm cuối cùng xóa .openlớp khỏi cha của nó.
  • Các phương thức được xâu chuỗi với nhau vì bộ chọn cho mỗi trình xử lý sự kiện là giống nhau

0

Giới thiệu

Tính đến thời điểm viết bài, câu trả lời ban đầu là 8 năm. Tôi vẫn cảm thấy dường như vẫn chưa có một giải pháp thích hợp cho câu hỏi ban đầu.

Bootstrap đã đi một chặng đường dài kể từ đó và bây giờ là 4.5.2 . Câu trả lời này giải quyết chính phiên bản này.

Vấn đề với tất cả các giải pháp khác cho đến nay

Vấn đề với tất cả các câu trả lời khác là, trong khi chúng tham gia vào show.bs.dropdown/ hide.bs.dropdown, các sự kiện tiếp theo shown.bs.dropdown/ hidden.bs.dropdownhoặc được kích hoạt quá sớm (hoạt ảnh vẫn đang diễn ra) hoặc chúng hoàn toàn không kích hoạt vì chúng đã bị chặn ( e.preventDefault()).

Một giải pháp sạch sẽ

Vì việc triển khai show()hide()trong Dropdownlớp Bootstraps có một số điểm tương đồng, tôi đã nhóm chúng lại với nhau toggleDropdownWithAnimation()khi bắt chước hành vi ban đầu và thêm các hàm trợ giúp QoL nhỏ vào showDropdownWithAnimation()hideDropdownWithAnimation().
toggleDropdownWithAnimation()tạo một shown.bs.dropdown/ hidden.bs.dropdownsự kiện giống như cách Bootstrap thực hiện. Sự kiện này sau đó được kích hoạt sau khi hoạt ảnh hoàn tất - giống như bạn mong đợi.

/**
 * Toggle visibility of a dropdown with slideDown / slideUp animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {boolean} show Show (true) or hide (false) the dropdown menu.
 * @param {number} duration Duration of the animation in milliseconds
 */
function toggleDropdownWithAnimation($containerElement, show, duration = 300): void {
    // get the element that triggered the initial event
    const $toggleElement = $containerElement.find('.dropdown-toggle');
    // get the associated menu
    const $dropdownMenu = $containerElement.find('.dropdown-menu');
    // build jquery event for when the element has been completely shown
    const eventArgs = {relatedTarget: $toggleElement};
    const eventType = show ? 'shown' : 'hidden';
    const eventName = `${eventType}.bs.dropdown`;
    const jQueryEvent = $.Event(eventName, eventArgs);

    if (show) {
        // mimic bootstraps element manipulation
        $containerElement.addClass('show');
        $dropdownMenu.addClass('show');
        $toggleElement.attr('aria-expanded', 'true');
        // put focus on initial trigger element
        $toggleElement.trigger('focus');
        // start intended animation
        $dropdownMenu
            .stop() // stop any ongoing animation
            .hide() // hide element to fix initial state of element for slide down animation
            .slideDown(duration, () => {
            // fire 'shown' event
            $($toggleElement).trigger(jQueryEvent);
        });
    }
    else {
        // mimic bootstraps element manipulation
        $containerElement.removeClass('show');
        $dropdownMenu.removeClass('show');
        $toggleElement.attr('aria-expanded', 'false');
        // start intended animation
        $dropdownMenu
            .stop() // stop any ongoing animation
            .show() // show element to fix initial state of element for slide up animation
            .slideUp(duration, () => {

            // fire 'hidden' event
            $($toggleElement).trigger(jQueryEvent);
        });
    }
}

/**
 * Show a dropdown with slideDown animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {number} duration Duration of the animation in milliseconds
 */
function showDropdownWithAnimation($containerElement, duration = 300) {
    toggleDropdownWithAnimation($containerElement, true, duration);
}

/**
 * Hide a dropdown with a slideUp animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {number} duration Duration of the animation in milliseconds
 */
function hideDropdownWithAnimation($containerElement, duration = 300) {
    toggleDropdownWithAnimation($containerElement, false, duration);
}

Ràng buộc người nghe sự kiện

Bây giờ chúng ta đã viết các lệnh gọi lại thích hợp để hiển thị / ẩn danh sách thả xuống với hoạt ảnh, hãy thực sự liên kết chúng với các sự kiện chính xác.

Một sai lầm phổ biến mà tôi đã thấy rất nhiều trong các câu trả lời khác là ràng buộc người nghe sự kiện trực tiếp với các phần tử. Mặc dù điều này hoạt động tốt cho các phần tử DOM có mặt tại thời điểm trình xử lý sự kiện được đăng ký, nhưng nó không liên kết với các phần tử được thêm vào sau này.

Đó là lý do tại sao bạn thường tốt hơn nên ràng buộc trực tiếp với document:

$(function () {

    /* Hook into the show event of a bootstrap dropdown */
    $(document).on('show.bs.dropdown', '.dropdown', function (e) {
        // prevent bootstrap from executing their event listener
        e.preventDefault();
        
        showDropdownWithAnimation($(this));
    });

    /* Hook into the hide event of a bootstrap dropdown */
    $(document).on('hide.bs.dropdown', '.dropdown', function (e) {
        // prevent bootstrap from executing their event listener
        e.preventDefault();
          
        hideDropdownWithAnimation($(this));
    });

});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.