猿问

CSS 过渡未按预期触发

下面的小提琴包含负责扩展可折叠菜单的代码。它类似于Bootstrap的Collapse组件。以下是它的工作原理:

  1. 菜单最初隐藏在 .display: none

  2. display: none被删除,使菜单可见,以便我们可以检索和存储其当前高度以供以后使用。

  3. 该菜单被赋予为该属性配置的 CSS 属性,该属性现在设置为 。transitionheight0

  4. 菜单的 设置为我们在步骤 2 中检索到的值。height

  5. 转换结束后,事件处理程序应启动。transitionend

尽管菜单会扩展到预期的高度,但它无需我们进行转换即可实现此目的。我需要你的帮助来找出原因。

在这里,试试吧:https://jsfiddle.net/avkdb89j/3/

一个重要的观察结果:如果打开检查器工具,选择(菜单)并切换代码在您单击按钮后添加的内联样式,则立即触发过渡,并执行处理程序。这里会是竞争条件吗?高度应该在设置过渡后更改,而不是在此之前更改。<nav>heighttransitionend


慕姐8265434
浏览 92回答 1
1回答

动漫人物

你需要摆脱并让css更多地照顾过渡。display: none我将 .np-collapsable 设置为 this,以便让元素始终存在:.np-collapsible:not(.np-expanded) {&nbsp; height: 0;&nbsp; overflow: hidden;}我将转换类设置为不进行任何会启动转换的更改(它仅包含 transition 属性)。然后在JS中,过渡与最初类似,但主要区别在于我使用菜单的高度,以避免额外的过渡以正常获得高度。menu.scrollHeight我还添加了将菜单收缩到函数的功能。在收缩菜单的情况下,由于选择器更早地停止溢出,因此必须在转换之前删除类:none。np-expanded:not(.np-expanded)&nbsp; // Retrieve the height of the menu&nbsp; var targetHeight = menu.scrollHeight + 'px';&nbsp; if (menu.classList.contains('np-expanded')) {&nbsp; &nbsp; // It's already expanded, time to contract.&nbsp; &nbsp; targetHeight = 0;&nbsp; &nbsp; menu.classList.remove('np-expanded');&nbsp; &nbsp; button.setAttribute('aria-expanded', false);&nbsp; }&nbsp; // Enable transition&nbsp; menu.classList.add('np-transitioning');&nbsp; menu.addEventListener('transitionend', function(event) {&nbsp; &nbsp; // Disable transition&nbsp; &nbsp; menu.classList.remove('np-transitioning');&nbsp; &nbsp; // Indicate that the menu is now expanded&nbsp; &nbsp; if (targetHeight) {&nbsp; &nbsp; &nbsp; menu.classList.add('np-expanded');&nbsp; &nbsp; &nbsp; button.setAttribute('aria-expanded', true);&nbsp; &nbsp; }&nbsp; }, {&nbsp; &nbsp; once: true&nbsp; });&nbsp; // Set the height to execute the transition&nbsp; menu.style.height = targetHeight;下面是一个工作示例:var button = document.querySelector('.np-trigger');var menu = document.querySelector(button.dataset.target);button.addEventListener('click', function(event) {&nbsp; expand();}, false);function expand() {&nbsp; if (isTransitioning()) {&nbsp; &nbsp; // Don't do anything during a transition&nbsp; &nbsp; return;&nbsp; }&nbsp; // Retrieve the height of the menu&nbsp; var targetHeight = menu.scrollHeight + 'px';&nbsp; if (menu.classList.contains('np-expanded')) {&nbsp; &nbsp; // It's already expanded, time to contract.&nbsp; &nbsp; targetHeight = 0;&nbsp; &nbsp; menu.classList.remove('np-expanded');&nbsp; &nbsp; button.setAttribute('aria-expanded', false);&nbsp; }&nbsp; // Enable transition&nbsp; menu.classList.add('np-transitioning');&nbsp; menu.addEventListener('transitionend', function(event) {&nbsp; &nbsp; // Disable transition&nbsp; &nbsp; menu.classList.remove('np-transitioning');&nbsp; &nbsp; // Indicate that the menu is now expanded&nbsp; &nbsp; if (targetHeight) {&nbsp; &nbsp; &nbsp; menu.classList.add('np-expanded');&nbsp; &nbsp; &nbsp; button.setAttribute('aria-expanded', true);&nbsp; &nbsp; }&nbsp; }, {&nbsp; &nbsp; once: true&nbsp; });&nbsp; // Set the height to execute the transition&nbsp; menu.style.height = targetHeight;}function isTransitioning() {&nbsp; if (menu.classList.contains('np-transitioning')) {&nbsp; &nbsp; return true;&nbsp; }&nbsp; return false;}.np-collapsible:not(.np-expanded) {&nbsp; height: 0;&nbsp; overflow: hidden;}.np-transitioning {&nbsp; transition: height 0.25s ease;}.navigation-menu {&nbsp; display: flex;&nbsp; flex-direction: column;&nbsp; position: fixed;&nbsp; top: 4rem;&nbsp; left: 1rem;&nbsp; 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">&nbsp; <a class="nav-link" href="#">Link</a>&nbsp; <a class="nav-link" href="#">Link</a>&nbsp; <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
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答