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
添加回答
举报