Bootstrap:使用单个选项卡导航控制多个选项卡面板

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

我想用一个选项卡导航来控制两个不同的选项卡内容。

在 Bootstra 3 中,我有一个用逗号分隔数据目标的解决方案(如本例所示:https://stackoverflow.com/a/19719859/1788961)。

但是在 Bootsrap 4 中,这种方式不再适用于选项卡。

折叠组件可以与多个目标一起使用,但我无法将其用于选项卡:https://getbootstrap.com/docs/4.0/components/collapse/#multiple-targets

还有其他方法可以做到这一点吗?

这是我的代码:

<div class="B">
    <div class="container">

        <div class="tab-content" id="ueberTabA">
            <div class="tab-pane fade" id="panel_a_first" role="tabpanel" aria-labelledby="first-tab">
                A First 
            </div>
            <div class="tab-pane fade show active" id="panel_a_second" role="tabpanel" aria-labelledby="second-tab">
                A Second
            </div>
            <div class="tab-pane fade" id="panel_a_third" role="tabpanel" aria-labelledby="third-tab">
                A Third
            </div>
        </div>
    </div>
</div>

<div class="container">
    <ul class="nav nav-tabs" id="ueberTab" role="tablist">
        <li class="nav-item"><a class="nav-link" id="first-tab" data-target="#panel_b_first, #panel_a_first" data-toggle="tab" href="#first" role="tab" aria-controls="first" aria-selected="false">first</a></li>
        <li class="nav-item"><a class="nav-link active" id="second-tab" data-target="#panel_b_second, #panel_a_second" data-toggle="tab" href="#second" role="tab" aria-controls="second" aria-selected="true">second</a></li>
        <li class="nav-item"><a class="nav-link" id="third-tab" data-target="#panel_b_thrid, #panel_a_third" data-toggle="tab" href="#third" role="tab" aria-controls="third" aria-selected="false">Unser third</a></li>
    </ul>
    <div class="tab-content" id="ueberTabB">
        <div class="tab-pane fade" id="panel_b_first" role="tabpanel" aria-labelledby="first-tab">
            B First 
        </div>
        <div class="tab-pane fade show active" id="panel_b_second" role="tabpanel" aria-labelledby="second-tab">
            B Second
        </div>
        <div class="tab-pane fade" id="panel_b_thrid" role="tabpanel" aria-labelledby="third-tab">
            B Third
        </div>
    </div>
</div>
jquery css twitter-bootstrap bootstrap-4 bootstrap-5
3个回答
6
投票

Bootstrap 5(2021 年更新)

这对于“开箱即用”的选项卡来说是不可能的。然而,JS 可以用来显示辅助选项卡窗格...


document.querySelectorAll('button[data-bs-toggle="tab"]').forEach((t,i)=>{
    t.addEventListener('show.bs.tab', function (e) {
        let targetClass = t.dataset.bsTarget
        var pane = document.querySelector('#secondTabContent '+targetClass)
        var sibling = document.querySelector('#secondTabContent .tab-pane.active')
        // hide 2nd pane sibling
        sibling.classList.remove('show')
        sibling.classList.remove('active')
        // show 2nd pane
        pane.classList.add('show')
        pane.classList.add('active')
    })  
})

Bootstrap 5 - 来自单个导航的多个选项卡窗格


Bootstrap 4(原始答案)

这在 Bootstrap 4.0.0 中是不可能的。目前这是一个悬而未决的问题,也是 Bootstrap 4.1 的一个可能的“想法”。

https://github.com/twbs/bootstrap/issues/19964


3
投票

我实际上已经找到了一种方法来完成这项工作。这不是最漂亮的解决方案,但它确实可以完成任务。

您需要执行以下操作:

$(document).on('click', '#ueberTab a', function(e) {
          otherTabs = $(this).attr('data-secondary').split(',');
          for(i= 0; i<otherTabs.length;i++) {
            nav = $('<ul class="nav d-none" id="tmpNav"></ul>');
            nav.append('<li class="nav-item"><a href="#" data-toggle="tab" data-target="' + otherTabs[i] + '">nav</a></li>"');
            nav.find('a').tab('show');
          }
        });
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script><div class="B">
    <div class="container">

        <div class="tab-content" id="ueberTabA">
            <div class="tab-pane fade" id="panel_a_first" role="tabpanel" aria-labelledby="first-tab">
                A First 
            </div>
            <div class="tab-pane fade show active" id="panel_a_second" role="tabpanel" aria-labelledby="second-tab">
                A Second
            </div>
            <div class="tab-pane fade" id="panel_a_third" role="tabpanel" aria-labelledby="third-tab">
                A Third
            </div>
        </div>
    </div>
</div>

<div class="container">
    <ul class="nav nav-tabs" id="ueberTab" role="tablist">
        <li class="nav-item"><a class="nav-link" id="first-tab" data-target="#panel_b_first" data-secondary="#panel_a_first" data-toggle="tab" href="#first" role="tab" aria-controls="first" aria-selected="false">first</a></li>
        <li class="nav-item"><a class="nav-link active" id="second-tab" data-target="#panel_b_second" data-secondary="#panel_a_second" data-toggle="tab" href="#second" role="tab" aria-controls="second" aria-selected="true">second</a></li>
        <li class="nav-item"><a class="nav-link" id="third-tab" data-target="#panel_b_thrid" data-secondary="#panel_a_third" data-toggle="tab" href="#third" role="tab" aria-controls="third" aria-selected="false">Unser third</a></li>
    </ul>
    <div class="tab-content" id="ueberTabB">
        <div class="tab-pane fade" id="panel_b_first" role="tabpanel" aria-labelledby="first-tab">
            B First 
        </div>
        <div class="tab-pane fade show active" id="panel_b_second" role="tabpanel" aria-labelledby="second-tab">
            B Second
        </div>
        <div class="tab-pane fade" id="panel_b_thrid" role="tabpanel" aria-labelledby="third-tab">
            B Third
        </div>
    </div>
</div>


0
投票

我想值得将 Carol Skelly 的答案 扩大到超过 2 个目标选项卡面板,并保持内置隐藏/显示动画正常工作。 BS 5 仅公开淡入淡出动画,所以让我们为其编写一个概念证明。

此外,BS 5 提供了一个带有导航链接的展示柜,如果您需要更复杂的布局,您可以删除它。

所以这是一个具有最小标记的概念证明:

/**
 * Allow a bootstrap single nav tab to target multiple tab panels
 */
document.querySelectorAll( '[data-bs-toggle="tab"][data-bs-target]' ).forEach( ( navTab ) => {
  const targetPanes = document.querySelectorAll( navTab.dataset.bsTarget )

  if( targetPanes.length > 1 ) {
    navTab.addEventListener( 'show.bs.tab', ( e ) => {
      const activeNav     = navTab.closest( '[role="tablist"]' ).querySelector( '.active[role="tab"]' )
      const activePanes   = document.querySelectorAll( activeNav.dataset.bsTarget )

      // Hide other panes
      activePanes.forEach( ( activePane ) => {
        // Ensure selector targets only tab panels
        if( activePane.matches( '[role="tabpanel"]' ) ) {
          const transProperty     = activePane.classList.contains( 'fade' ) ? 'opacity' : null
          const outTransDuration  = transProperty ? utils.toMilliseconds( utils.getComputedTransitions( activePane, '', transProperty ).duration ) : 0

          // Remove class making pane visible
          activePane.classList.remove( 'show' )
          // Wait for transition...
          setTimeout( () => {
            // Then hide pane
            activePane.classList.remove( 'active' )

            targetPanes.forEach( ( targetPane ) => {
              // Ensure selector targets only tab panels
              if( targetPane.matches( '[role="tabpanel"]' ) ) {
                const transProperty   = targetPane.classList.contains( 'fade' ) ? 'opacity' : null
                const inTransDuration = transProperty ? utils.toMilliseconds( utils.getComputedTransitions( targetPane, '', transProperty ).duration ) : 0
                
                // Show pane
                targetPane.classList.add( 'active' )
                // Can't figure why, but this ensures animation of target panes beyond first lasts as long as animation of first
                setTimeout( () => {
                  targetPane.classList.add( 'show' )
                }, 0 )
              }
            } )
          }, outTransDuration )
        }
      } )

    } )
  }
} )

/**
 * Utils to get transition duration of a CSS property
 */
const utils = {
  getComputedTransitions: ( elem, pseudo, property ) => {

    const computedStyles    = window.getComputedStyle( elem, pseudo )
    const delays                    = computedStyles.getPropertyValue( 'transition-delay' ).split( ', ' )
    const durations             = computedStyles.getPropertyValue( 'transition-duration' ).split( ', ' )
    const properties            = computedStyles.getPropertyValue( 'transition-property' ).split( ', ' )
    const timingFunctions   = computedStyles.getPropertyValue( 'transition-timing-function' ).split( ', ' )
  
    let transitions = {}
  
    for( let i in properties ) {
      transitions[properties[i] || 'all'] = {
        duration: durations[i],
        delay: delays[i],
        timingFunction: timingFunctions[i],
      }
    }
  
    if( property ) {
      return transitions[property] ? transitions[property] : transitions['all']
    }
  
    return transitions
  
  },

  toMilliseconds: ( string ) => {

    if( string.match( /^[0-9.]+s$/g ) ) {
      return parseFloat( string ) * 1000
    }
    if( string.match( /^[0-9.]+ms$/g ) ) {
      return parseFloat( string )
    }
  
    return string
  
  }
    
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div role="tablist">
  <button type="button" class="active" data-bs-toggle="tab" data-bs-target=".pane-first" role="tab" aria-controls="pane-first" aria-selected="true">Tab first</button>
  <button type="button" data-bs-toggle="tab" data-bs-target=".pane-second" role="tab" aria-controls="pane-first" aria-selected="false">Tab second</button>
</div>
...
<div class="tab-content">
  <div class="tab-pane fade pane-first active show" role="tabpanel">Block 1, pane first</div>
  <div class="tab-pane fade pane-second" role="tabpanel">Block 1, pane second</div>
</div>
...
<div class="tab-content">
  <div class="tab-pane fade pane-first active show" role="tabpanel">Block 2, pane first</div>
  <div class="tab-pane fade pane-second" role="tabpanel">Block 2, pane second</div>
</div>

淡入淡出过渡并不是真正同步的。我猜本地 BS 功能会在块 1 选项卡面板切换时产生干扰。

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