You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3项目中Bootstrap 5标签页点击后内容无法切换的解决

修复Vue3 + Bootstrap5标签页内容不切换的问题

问题根源很明确:NavBar组件和App组件各自维护了独立的activeTab状态,点击标签时只有NavBar的状态更新了,App里控制内容显示的activeTab完全没变化,所以内容一直停留在初始标签。

直接上修复方案:

1. 把状态统一到父组件(App.vue)

把activeTab的控制权交给App.vue,NavBar只负责触发切换事件,不维护自己的状态。

修改NavBar.vue

  • 把activeTab从data移到props里
  • 点击标签时通过$emit通知父组件切换状态
  • 阻止a标签的默认跳转行为(避免页面滚动到锚点)
<template>
  <div id="navs" class="m-2">
    <ul class="nav nav-tabs" role="tablist">
      <li class="nav-item">
        <a
          class="nav-link"
          :class="{ active: activeTab === 'web' }"
          @click.prevent="$emit('tab-change', 'web')"
          href="#web"
        ><font-awesome-icon icon="globe"/></a>
      </li>
      <li class="nav-item">
        <a
          class="nav-link"
          :class="{ active: activeTab === 'flag' }"
          @click.prevent="$emit('tab-change', 'flag')"
          href="#flag"
        ><font-awesome-icon icon="flag"/></a>
      </li>
      <li class="nav-item">
        <a
          class="nav-link"
          :class="{ active: activeTab === 'fb' }"
          @click.prevent="$emit('tab-change', 'fb')"
          href="#fb"
        ><font-awesome-icon :icon="{ prefix: 'fab', iconName: 'facebook' }"/></a>
      </li>
      <li class="nav-item">
        <a
          class="nav-link"
          :class="{ active: activeTab === 'twitter' }"
          @click.prevent="$emit('tab-change', 'twitter')"
          href="#twitter"
        ><font-awesome-icon :icon="{ prefix: 'fab', iconName: 'square-x-twitter' }"/></a>
      </li>
      <li class="nav-item">
        <a
          class="nav-link"
          :class="{ active: activeTab === 'yt' }"
          @click.prevent="$emit('tab-change', 'yt')"
          href="#yt"
        ><font-awesome-icon :icon="{ prefix: 'fab', iconName: 'youtube' }"/></a>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "NavBar",
  props: {
    activeTab: {
      type: String,
      required: true
    }
  }
};
</script>

<style scoped>
/* Add your component-specific styles here */
</style>

修改App.vue

  • 给NavBar组件绑定activeTab属性,把自己的状态传过去
  • 监听tab-change事件,更新自己的activeTab
  • 补上fb、twitter、yt对应的tab-content(不然点击这些标签看不到内容)
<template>
  <div id="container">
    <NavBar :activeTab="activeTab" @tab-change="activeTab = $event" />
    <div class="tab-content">
      <div
        id="web"
        class="container tab-pane"
        :class="{ active: activeTab === 'web' }"
      >
        <h3 class="text-danger">Web</h3>
        <BaseElements />
        <chart></chart>
      </div>
      <div
        id="flag"
        class="container tab-pane"
        :class="{ active: activeTab === 'flag' }"
      >
        <h3 class="text-light">Country</h3>
      </div>
      <!-- 补上剩下的标签内容 -->
      <div
        id="fb"
        class="container tab-pane"
        :class="{ active: activeTab === 'fb' }"
      >
        <h3 class="text-light">Facebook</h3>
      </div>
      <div
        id="twitter"
        class="container tab-pane"
        :class="{ active: activeTab === 'twitter' }"
      >
        <h3 class="text-light">Twitter</h3>
      </div>
      <div
        id="yt"
        class="container tab-pane"
        :class="{ active: activeTab === 'yt' }"
      >
        <h3 class="text-light">Youtube</h3>
      </div>
    </div>
  </div>
</template>

<script>
import "bootstrap/dist/css/bootstrap.min.css";
import NavBar from "./components/navBar.vue";
import BaseElements from "./components/BaseElements.vue";
import BarChart from "./components/BarChart";

export default {
  name: "App",
  components: {
    NavBar,
    BaseElements,
    chart: BarChart,
  },
  data() {
    return {
      activeTab: "web",
    };
  },
  methods: {
    handler() {
      var args = arguments;
      for (var arg of args) {
        if (arg instanceof Function) {
          arg();
        }
      }
    },
  },
};
</script>

<style>
body {
  margin: 0;
  background-color: #002a53 !important;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
    "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
    monospace;
}
</style>

2. 额外优化(可选)

如果想直接用Bootstrap的原生JS功能,也可以不用Vue的状态管理,只需要给标签和内容加上正确的Bootstrap属性:

  • 给a标签加data-bs-toggle="tab"和data-bs-target="#xxx"
  • 给内容容器加role="tabpanel"

这种方式不需要写Vue的状态和事件,但需要确保Bootstrap的JS已经引入(你已经安装了bootstrap和@popperjs/core,只需要在App.vue里导入bootstrap/dist/js/bootstrap.min.js)。不过这种方式和Vue的响应式结合起来可能不如第一种灵活,推荐用第一种Vue原生的状态管理方式。

内容的提问来源于stack exchange,提问作者nb_nb_nb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 15:57:07