如何在显示时使用 jQuery 对元素进行操作:无

Posted

技术标签:

【中文标题】如何在显示时使用 jQuery 对元素进行操作:无【英文标题】:How to operate on element using jQuery whilst it is display:none 【发布时间】:2018-11-27 02:01:20 【问题描述】:

场景

我有一个仪表板,其中一些小部件分组到用户可以单击的选项卡中。小部件具有默认的起始高度,当它们包含的内容(图表、图形、表格等)呈现时,它们的高度会更新。

我目前仅在页面加载时更新活动选项卡中小部件的高度,然后当用户单击不同的选项卡时更新这些小部件。

问题

我必须使用setTimeout 以确保在更新高度之前活动选项卡可见,这意味着小部件在单击后会立即向下滑动,而不是立即以最佳高度出现。

问题

    有没有办法在加载时更新所有小部件的高度,即使是隐藏在其他选项卡上的带有 display:none 的小部件?

我尝试使用 :visible:hidden 选择器,但没有成功。

    我是否应该坚持我目前的性能方法,因为最终可能会有许多小部件跨越许多选项卡?如果是这样,是否可以在没有setTimeout 的情况下完成,因为我只是猜测 200 毫秒的延迟就足够了。

剥离示例

下面的例子,加上Codepen。

$(document).foundation();

$(function () 
  var options = 
    cellHeight: 40,
    verticalMargin: 28,
    animate: true,
  ;

  widgetsInit = function(options) 
    var targetPanel = '.tabs-panel.is-active';

    setTimeout(function()
      $(targetPanel + ' .grid-stack').gridstack(options);

      $(targetPanel + ' .grid-stack .grid-stack-item').each(function(i)
        $(targetPanel + ' .grid-stack').data('gridstack').resize(
          $(targetPanel + ' .grid-stack .grid-stack-item')[i],
          $($(targetPanel + ' .grid-stack .grid-stack-item')[i]).attr('data-gs-width'),
          Math.ceil(($(targetPanel + ' .grid-stack .grid-stack-item .grid-stack-item-content')[i].scrollHeight + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin) / ($(targetPanel + ' .grid-stack').data('gridstack').cellHeight() + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin))
        );
      );
    , 200);
  

  widgetsInit(options);

  $('.tabs-title').on('click', function(e) 
    widgetsInit(options);
  )
);
.grid-stack > .grid-stack-item > .grid-stack-item-content 
    background-color: #fff;
    cursor: move;
    border: 1px solid #e3e3e3;
    border-radius: 4px;
	  padding: 1rem;
<link href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.jQueryUI.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js"></script>

<!-- Tabs start -->
<ul class="tabs dashboard-tabs" data-tabs id="example-tabs" data-deep-link="true" data-update-history="true" data-match->
  <li class="tabs-title is-active"><a href="#panel1" aria-selected="true">Panel 1</a></li>
  <li class="tabs-title"><a href="#panel2">Panel 2</a></li>
</ul>
<!-- Tabs end -->

<!-- Panels start -->
<div class="tabs-content unstyled" data-tabs-content="example-tabs">
  
  <!--  Panel 1 start  -->
  <div class="tabs-panel is-active" id="panel1">
    <div class="grid-stack">
      <div class="grid-stack-item" data-custom-id="0" data-gs-x="0" data-gs-y="0" data-gs->
        <div class="grid-stack-item-content">
          #0<br>
          <iframe   src="https://www.youtube.com/embed/VUuBJ0ietME" frameborder="0"></iframe>
          </div>
      </div>
      <div class="grid-stack-item" data-custom-id="1" data-gs-x="4" data-gs-y="0" data-gs->
        <div class="grid-stack-item-content">
          #1
        </div>
      </div>
      <div class="grid-stack-item" data-custom-id="2" data-gs-x="8" data-gs-y="0" data-gs->
        <div class="grid-stack-item-content">#2</div>
      </div>
      <div class="grid-stack-item" data-custom-id="3" data-gs-x="0" data-gs-y="1" data-gs->
        <div class="grid-stack-item-content">#3</div>
      </div>
    </div>
  </div>
  <!-- Panel 1 end -->
  
  <!-- Panel 2 start -->
  <div class="tabs-panel" id="panel2">
    <div class="grid-stack">
      <div class="grid-stack-item" data-custom-id="4" data-gs-x="0" data-gs-y="0" data-gs->
        <div class="grid-stack-item-content">
          #4<br>
          <iframe   src="https://www.youtube.com/embed/a4fv-BtzNmY" frameborder="0"></iframe>
        </div>
      </div>
      <div class="grid-stack-item" data-custom-id="5" data-gs-x="6" data-gs-y="0" data-gs->
        <div class="grid-stack-item-content">#5</div>
      </div>
    </div>
  </div>
  <!-- Panel 2 end -->
  
</div>
<!-- Panels end -->

【问题讨论】:

【参考方案1】:

这里有一些事情在起作用。我已经创建了一个关于如何处理它的分支。 https://codepen.io/matthewblewitt/pen/KeybxG

我使用基础选项卡 API 而不是单击事件触发了 gridstack 插件,因此您可以删除 setTimeout。

$(document).on('change.zf.tabs', function(e) 
   widgetsInit(options);
);

基础选项卡使用display: none 隐藏非活动选项卡,而gridstack 插件似乎与该属性不兼容。因此,我更改了 CSS 以隐藏屏幕上的非活动选项卡,并使用 CSS 不透明度和禁用 gridstack 的动画来淡化它们。

.tabs-panel 
  position: absolute; 
  overflow: hidden; 
  height: 1px; 
  width: 1px; 
  opacity: 0;
  transition: 0.75s opacity ease;
  display: block;

.tabs-panel.is-active 
  position: static;
  overflow: visible;
  width: auto;
  height: auto; 
  opacity: 1;

希望这会有所帮助。

【讨论】:

更多关于事件驱动基础选项卡 API 的信息在这里 foundation.zurb.com/sites/docs/tabs.html#js-events 我喜欢这种方法,褪色看起来很优雅。谢谢。

以上是关于如何在显示时使用 jQuery 对元素进行操作:无的主要内容,如果未能解决你的问题,请参考以下文章

jQuery - 不可见时获取元素的宽度(显示:无)

如何在使用 jquery ui 删除时对元素进行排序?

当动态值匹配时,jQuery 按类对元素进行分组

如何使用 jQuery 对表单提交进行验证

jQuery 对象和 DOM 元素

jQuery 选择器