为了账号安全,请及时绑定邮箱和手机立即绑定

CSS 过渡未按预期触发

CSS 过渡未按预期触发

慕姐8265434 2022-08-27 09:56:44
下面的小提琴包含负责扩展可折叠菜单的代码。它类似于Bootstrap的Collapse组件。以下是它的工作原理:菜单最初隐藏在 .display: nonedisplay: none被删除,使菜单可见,以便我们可以检索和存储其当前高度以供以后使用。该菜单被赋予为该属性配置的 CSS 属性,该属性现在设置为 。transitionheight0菜单的 设置为我们在步骤 2 中检索到的值。height转换结束后,事件处理程序应启动。transitionend尽管菜单会扩展到预期的高度,但它无需我们进行转换即可实现此目的。我需要你的帮助来找出原因。在这里,试试吧:https://jsfiddle.net/avkdb89j/3/一个重要的观察结果:如果打开检查器工具,选择(菜单)并切换代码在您单击按钮后添加的内联样式,则立即触发过渡,并执行处理程序。这里会是竞争条件吗?高度应该在设置过渡后更改,而不是在此之前更改。<nav>heighttransitionend
查看完整描述

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


查看完整回答
反对 回复 2022-08-27
  • 1 回答
  • 0 关注
  • 91 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信