如何立即在BootstrapVue中显示新打开的标签页内容? 示例

问题描述

早上好

我的目标是:

每次打开新标签页时,该标签页都将变为“活动”状态,并且浏览器会显示内容

  • 问题:每次打开新标签页时,以前打开的标签页都保持“活动”状态。

Look at a trivial example of the problem.

为了重现问题:

  1. 访问BootstrapVue Playground;
  2. 滚动到页面底部的“ Dynamic tabs + tabs-end slot”部分(在高级示例部分中提供);
  3. 双击代码区域(以便进行修改);
  4. 粘贴以下代码
<template>
  <div>
    <b-card no-body>
      <b-tabs card>
        <!-- Render Tabs,supply a unique `key` to each tab -->
        <b-tab v-for="tab in tabs" :key="tab.id" :class="{active:tab.isActive}" :title="'Tab ' + tab.id">
          Tab contents {{ tab.id }}
          <b-button size="sm" variant="danger" class="float-right" @click="closeTab(tab.id)">
            Close tab
          </b-button>
        </b-tab>

        <!-- New Tab Button (Using tabs-end slot) -->
        <template v-slot:tabs-end>
          <b-nav-item role="presentation" @click.prevent="newTab" href="#"><b>+</b></b-nav-item>
        </template>

        <!-- Render this if no tabs -->
        <template v-slot:empty>
          <div class="text-center text-muted">
            There are no open tabs<br>
            Open a new tab using the <b>+</b> button above.
          </div>
        </template>
      </b-tabs>
    </b-card>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        tabs: [],tabCounter: 0,activeTab: {}
      }
    },methods: {
      closeTab(x) {
        for (let i = 0; i < this.tabs.length; i++) {
          if (this.tabs[i].id === x) {
            this.tabs.splice(i,1)
          }
        }
      },newTab() {
        const newTab = {
          id: this.tabCounter,isActive: true
        };
        this.tabCounter++;
        this.tabs.push(newTab);
        this.setActive(newTab);
      },setActive(tab) {
        tab.isActive = true;
        this.activeTab = tab;
        this.tabs.forEach((tab) => {
          if (tab.id !== this.activeTab.id) {
            tab.isActive = false;
          }
        })
      }
    }
  }
</script>
  1. 尝试通过单击呈现区域中的“ +”按钮来添加标签,该区域位于粘贴代码的开头。

我在做什么错了?

解决方法

使用 b-tabs

  1. 事件:changed
  2. 属性:v-model
<b-tabs v-model="tabActive" @changed="onTabChanged">

data() {
  return {
    tabActive: 0,tabs:[],}

onTabChanged() {
  this.tabActive = this.tabs.length - 1;
},
,

您可以通过在active上添加<b-tab>道具来完成此操作,这将使新创建的标签页成为活动标签页。

<b-tab active ...>

示例

new Vue({
  el: "#app",data() {
    return {
      tabs: [],tabCounter: 0
    }
  },methods: {
    closeTab(x) {
      for (let i = 0; i < this.tabs.length; i++) {
        if (this.tabs[i] === x) {
          this.tabs.splice(i,1)
        }
      }
    },newTab() {
      this.tabs.push(this.tabCounter++)
    }
  }
});
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.js"></script>

<div id="app">
  <b-card no-body>
    <b-tabs card>
      <!-- Render Tabs,supply a unique `key` to each tab -->
      <b-tab v-for="i in tabs" :key="'dyn-tab-' + i" :title="'Tab ' + i" active>
        Tab contents {{ i }}
        <b-button size="sm" variant="danger" class="float-right" @click="closeTab(i)">
          Close tab
        </b-button>
      </b-tab>

      <!-- New Tab Button (Using tabs-end slot) -->
      <template v-slot:tabs-end>
        <b-nav-item role="presentation" @click.prevent="newTab" href="#"><b>+</b></b-nav-item>
      </template>

      <!-- Render this if no tabs -->
      <template v-slot:empty>
        <div class="text-center text-muted">
          There are no open tabs<br>
          Open a new tab using the <b>+</b> button above.
        </div>
      </template>
    </b-tabs>
  </b-card>
</div>

,

您好,MIchele Rosito,

b-tabs组件接受一个值,该值是选定的选项卡索引(通过v-model传递)

下面我有一个工作原型的简化版本,我认为它可以完成您的工作。

但是有一个陷阱,添加一个新选项卡时,将通过在(虚拟)DOM上引导来呈现它,这将花费一些时间,并且我们无法选择尚未呈现的选项卡。

“解决方案”(不是很好的绷带)是给它几毫秒的时间,然后才更改“ tabIndex”以给标签渲染一些时间。

这不是最佳的生产解决方案,但我认为它可以为您指明正确的方向。

<template>
  <div>
    <b-card no-body>
      <b-tabs card v-model="tabIndex">
        <!-- Render Tabs,supply a unique `key` to each tab -->
        <b-tab v-for="tab in tabs" :key="tab.id" :class="{active:tab.isActive}" :title="'Tab ' + tab.id">
          Tab contents {{ tab.id }}
          <b-button size="sm" variant="danger" class="float-right" @click="closeTab(tab.id)">
            Close tab
          </b-button>
        </b-tab>

        <!-- New Tab Button (Using tabs-end slot) -->
        <template v-slot:tabs-end>
          <b-nav-item role="presentation" @click.prevent="newTab" href="#"><b>+</b></b-nav-item>
        </template>

        <!-- Render this if no tabs -->
        <template v-slot:empty>
          <div class="text-center text-muted">
            There are no open tabs<br>
            Open a new tab using the <b>+</b> button above.
          </div>
        </template>
      </b-tabs>
    </b-card>
 </div>
</template>

<script>
  export default {
    data() {
      return {
        tabs: [],tabIndex: 0,tabCounter: 0,activeTab: {}
      }
    },methods: {
      closeTab(x) {
        for (let i = 0; i < this.tabs.length; i++) {
          if (this.tabs[i].id === x) {
            this.tabs.splice(i,1)
          }
        }
      },newTab() {
        const newTab = {
          id: this.tabCounter,};
        this.tabCounter++;
        this.$set(this,tabs,this.tabs.push(newTab));  
        setTimeout(() => { this.tabIndex = this.tabs.length;},100);      
      }
    }
  }
</script>

有帮助吗?