1 回答

TA貢獻1815條經驗 獲得超10個贊
你需要擺脫并讓css更多地照顧過渡。display: none
我將 .np-collapsable 設置為 this,以便讓元素始終存在:
.np-collapsible:not(.np-expanded) {
height: 0;
overflow: hidden;
}
我將轉換類設置為不進行任何會啟動轉換的更改(它僅包含 transition 屬性)。
然后在JS中,過渡與最初類似,但主要區別在于我使用菜單的高度,以避免額外的過渡以正常獲得高度。menu.scrollHeight
我還添加了將菜單收縮到函數的功能。在收縮菜單的情況下,由于選擇器更早地停止溢出,因此必須在轉換之前刪除類:none。np-expanded:not(.np-expanded)
// Retrieve the height of the menu
var targetHeight = menu.scrollHeight + 'px';
if (menu.classList.contains('np-expanded')) {
// It's already expanded, time to contract.
targetHeight = 0;
menu.classList.remove('np-expanded');
button.setAttribute('aria-expanded', false);
}
// Enable transition
menu.classList.add('np-transitioning');
menu.addEventListener('transitionend', function(event) {
// Disable transition
menu.classList.remove('np-transitioning');
// Indicate that the menu is now expanded
if (targetHeight) {
menu.classList.add('np-expanded');
button.setAttribute('aria-expanded', true);
}
}, {
once: true
});
// Set the height to execute the transition
menu.style.height = targetHeight;
下面是一個工作示例:
var button = document.querySelector('.np-trigger');
var menu = document.querySelector(button.dataset.target);
button.addEventListener('click', function(event) {
expand();
}, false);
function expand() {
if (isTransitioning()) {
// Don't do anything during a transition
return;
}
// Retrieve the height of the menu
var targetHeight = menu.scrollHeight + 'px';
if (menu.classList.contains('np-expanded')) {
// It's already expanded, time to contract.
targetHeight = 0;
menu.classList.remove('np-expanded');
button.setAttribute('aria-expanded', false);
}
// Enable transition
menu.classList.add('np-transitioning');
menu.addEventListener('transitionend', function(event) {
// Disable transition
menu.classList.remove('np-transitioning');
// Indicate that the menu is now expanded
if (targetHeight) {
menu.classList.add('np-expanded');
button.setAttribute('aria-expanded', true);
}
}, {
once: true
});
// Set the height to execute the transition
menu.style.height = targetHeight;
}
function isTransitioning() {
if (menu.classList.contains('np-transitioning')) {
return true;
}
return false;
}
.np-collapsible:not(.np-expanded) {
height: 0;
overflow: hidden;
}
.np-transitioning {
transition: height 0.25s ease;
}
.navigation-menu {
display: flex;
flex-direction: column;
position: fixed;
top: 4rem;
left: 1rem;
width: 270px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<button class="btn btn-dark np-trigger" data-target="#menu">Menu</button>
<nav id="menu" class="bg-dark navigation-menu np-collapsible">
<a class="nav-link" href="#">Link</a>
<a class="nav-link" href="#">Link</a>
<a class="nav-link" href="#">Link</a>
</nav>
展開代碼段
如前所述,原始版本中存在一個爭用條件,因為通過按原始狀態設置類來啟動多個轉換。此方法通過保持簡單性來避免與其他爭用條件的問題。display: none
有趣的是,將 ) 線向上移動到與移除相同的位置可以使其工作。我覺得可能只是這些變化在這一點上基本上是一起批處理的。原始jquery代碼工作的原因可能是因為它添加了/刪除了類,而沒有在兩者之間進行任何其他DOM工作。menu.classList.add('np-transitioningnp-collapsible
以下是在上述方法中工作的原始更新 https://jsfiddle.net/5w12rcbh/
這是相同的更新,但使用諸如一次執行更多工作之類的方法進行了擴展和清理。這增加了與我的原始代碼段相同的切換功能。https://jsfiddle.net/bzc7uy2s/classList.replace
添加回答
舉報