如何动态地将溢出元素推入下拉列表

问题描述 投票:0回答:1

问题陈述

我有一个简单的动态导航栏(项目数量和文本可以更改)。我想显示屏幕上可以容纳在一行中的前 X 个项目以及“显示更多”下拉列表,所有溢出的项目都将进入其中,即在将前 X 个项目容纳在一行中后留下的项目。

可能的解决方案

我尝试通过计算每个项目的宽度(文本宽度+按钮填充)、检查屏幕宽度,然后仅放置组合宽度(加上“显示更多”按钮的宽度)的前 X 个项目来实现此目的小于屏幕宽度。现在具有挑战性的部分是计算文本宽度。如果我们首先渲染所有元素,那么很容易获得每个项目的渲染宽度,然后我们可以进行上述计算来检查哪些元素适合单行。然而,这种方法最初会渲染所有元素,并不是性能优化的解决方案。

javascript html css reactjs
1个回答
0
投票

要计算每个项目的宽度,它必须由浏览器渲染。找到一个不首先渲染的解决方案听起来很像“过早优化”。除非菜单中有数千个顶级项目,否则渲染它们所花费的时间可以忽略不计;特别是与运行替代脚本解决方案所需的时间相比。 如下面的代码所示,JavaScript 逻辑非常简单,并且不会对性能产生任何明显的影响。整个顶级项目列表只需要迭代一次。

window.addEventListener( 'DOMContentLoaded', () => { const menu = document.querySelector( '#menu' ) const items = menu.querySelectorAll( '.item' ) const viewMore = menu.querySelector( '.view-more' ) const overflow = menu.querySelector( '#overflow-menu' ) const overflowItems = [] const maxWidth = menu.offsetWidth let accumulator = viewMore.offsetWidth let c = 0 while ( accumulator <= maxWidth && c < items.length - 1 ) { accumulator += items[c].offsetWidth c++ } for ( c--; c < items.length; c++ ) { if ( ! items[c].classList.contains( 'view-more' ) ) { overflow.appendChild(items[c]); } } viewMore.addEventListener( 'click', () => { overflow.classList.toggle( 'visible' ) } ) } )
#menu {
    display: flex;
}
.item {
    padding: 5px 10px;
    cursor: pointer;
    white-space: nowrap;
    color: black;
}
.item.view-more {
    background-color: black;
    color: white;
    border-radius: 5px;
    position: relative;
}
#overflow-menu {
    position: absolute;
    top: 100%;
    right: 0;
    display: none;
    flex-direction: column;
    background-color: white;
    box-shadow: 0 0 10px black;
}
#overflow-menu.visible {
    display: flex;
}
<div id="menu">
  <div class="item">Text</div>
  <div class="item">Of Varying</div>
  <div class="item">Lengths</div>
  <div class="item">That The Browser</div>
  <div class="item">Must</div>
  <div class="item">Render</div>
  <div class="item">In</div>
  <div class="item">Order To</div>
  <div class="item">Determine</div>
  <div class="item">The</div>
  <div class="item">Final Width</div>
  <div class="item">:)</div>
  
  <div class="item view-more">
      View More
      <div id="overflow-menu"></div>
  </div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.