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

Vue Composition API下如何将含静态tabs的Nav组件改为Props动态传值

改造方案

1. 修改ProgramModal子组件

第一步:定义Tab项类型并声明Props

你提到的泛型定义在Vue2组合式API中可以通过Array as () => 自定义类型[]的方式实现,我们同时将选中状态放到子组件内部维护,避免直接修改props违反单向数据流规则:

<template>
  <div>
    <div class="sm:hidden">
      <label for="tabs" class="sr-only">Select a tab</label>
      <select
        id="tabs"
        name="tabs"
        class="block w-full focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md"
      >
        <option v-for="tab in tabs" :key="tab.name" :selected="tab.id === currentActiveId">
          {{ tab.name }}
        </option>
      </select>
    </div>

    <div class="hidden sm:block">
      <nav class="flex items-center space-x-4">
        <a
          v-for="tab in tabs"
          :key="tab.name"
          :href="tab.href"
          :class="[
            tab.id === currentActiveId
              ? 'bg-purple-70 q0 text-white'
              : 'text-purple-700 hover:text-gray-700',
            'px-12 py-2 rounded-full font-bold text-xl',
          ]"
          @click="changeTab(tab)"
        >
          {{ tab.name }}
        </a>
      </nav>
    </div>
    <div class="hidden sm:block">
      <div
        v-for="tab in tabs"
        :key="tab.name"
        :href="tab.href"
        class="px-12 flex justify-center"
        :class="[tab.id === currentActiveId || 'hidden']"
        @click="changeTab(tab)"
      >
        {{ tab.id }} - {{ tab.name }} - {{ tab.href }} - {{ tab.title }}
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, computed } from '@vue/composition-api'
import i18n from '@/setup/i18n'

// 定义Tab项的泛型接口
export interface TabItem {
  id: number
  title: string
  imageSrc: string
  content: string
  name: string
  href: string
}

export default defineComponent({
  name: 'ProgramModal',
  // 声明接收的props
  props: {
    tabs: {
      // 泛型定义数组类型
      type: Array as () => TabItem[],
      required: false,
      // 保留原来的静态数据作为默认值,不传props也能正常运行
      default: () => [
        {
          id: 1,
          title: 'test title one',
          imageSrc: '/programs/test1.png',
          content: '',
          name: 'LOREM',
          href: '#test1',
        },
        {
          id: 2,
          title: 'test title two',
          imageSrc: '/programs/test2.png',
          content: '',
          name: 'IPSUM',
          href: '#test2',
        },
        {
          id: 3,
          title: 'test title three',
          imageSrc: '/programs/test3.png',
          content: '',
          name: 'PDF',
          href: '#test3',
        },
      ]
    },
    // 可选:支持父组件指定默认选中的tab id
    defaultActiveId: {
      type: Number,
      default: 1
    }
  },
  setup(props) {
    const ariaLabel = computed(() => i18n.t('share') as string)
    // 内部维护选中状态,不直接修改父组件传入的props
    const currentActiveId = ref(props.defaultActiveId)

    const changeTab = (selectedTab: TabItem) => {
      currentActiveId.value = selectedTab.id
    }

    return {
      currentActiveId,
      changeTab,
      ariaLabel,
    }
  },
})
</script>

2. 修改父组件传入自定义tabs

父组件中定义自己需要的tabs数组,通过props传给子组件即可:

<template>
  <!-- 传入自定义tabs,也可以指定defaultActiveId修改默认选中项 -->
  <ProgramModal :tabs="customTabs" :default-active-id="2" />
</template>


<script lang="ts">
import ProgramModal, { TabItem } from '@/components/ProgramModal.vue'
import { defineComponent, ref } from '@vue/composition-api'

export default defineComponent({
  name: 'Home',

  components: {
    ProgramModal,
  },

  setup() {
    const isModalOpen = ref(true)

    const showModal = () => {
      isModalOpen.value = true
    }

    // 自定义要传入的tabs数据,可根据业务需求动态修改
    const customTabs = ref<TabItem[]>([
      {
        id: 1,
        title: '首页',
        imageSrc: '/programs/home.png',
        content: '首页内容',
        name: '首页',
        href: '#home',
      },
      {
        id: 2,
        title: '数据列表',
        imageSrc: '/programs/list.png',
        content: '列表内容',
        name: '列表',
        href: '#list',
      },
      {
        id: 3,
        title: '个人中心',
        imageSrc: '/programs/mine.png',
        content: '我的内容',
        name: '我的',
        href: '#mine',
      },
    ])

    return {
      isModalOpen,
      showModal,
      customTabs
    }
  },
})
</script>

扩展说明:如果需要父组件控制选中状态

如果你的业务需要父组件完全管控tab的选中状态,可以将子组件内部的currentActiveId改为通过emit通知父组件修改,父组件再通过prop把选中值传回来,也就是标准的v-model双向绑定模式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 00:45:05