我想使用 emit 在页面组件之间切换

I want to use emit to switch between page components

我现在在Top page 上有一个Header 和一个Main page,在Header 组件中我有三个Tab 功能。当我按下每个选项卡(A、B、C)时,我想在主页中切换显示(A、B、C)。我正在尝试使用 Emit 更改它,但它不起作用。如果您能给我一些建议,我将不胜感激。

Header.vue

<script setup >
const tabs = [
  {name: 'A', comp: A},
  {name: 'B', comp: B},
  {name: 'C', comp: C}
];

interface Emits {
  (e: "clicked", value: any);
}

const clicked = defineEmits<Emits>();
</script>

<template>
<div class="tabs" >
        <button v-bind:class="['tab-button', A]" @click="$emit('clickedA',tabs[0])">A</button>
        <button v-bind:class="['tab-button', B]" @click="$emit('clickedB',tabs[1])">B</button>
        <button v-bind:class="['tab-button', C]" @click="$emit('clickedC',tabs[2])">C</button>
</div>
</template>

Mainpage.vue


<script>
let currentTab = A

function getValue(event) {
    currentTab = event
}


</ script>

<template>
  <Header />
  <div>
    <component :is="currentTab" @clicked="getValue"></component> 
  </div>
</template>

我会让 3 个按钮都调用相同的 emit 方法,传入组件字符串作为该 emit 的参数:

<button v-bind:class="['tab-button']" 
    @click="$emit('myClicked', tabs[0])">
    A
</button>
<button v-bind:class="['tab-button']" 
    @click="$emit('myClicked', tabs[1])">
    B
</button>
<button v-bind:class="['tab-button']" 
    @click="$emit('myClicked', tabs[2])">
    C
</button>

然后,在父组件中,您可以单独监听那个发射器:

<Header @myClicked="getValue" />

在脚本中:

function getValue(tab) {
  currentTab.value = tab.name;
}

例如:

Mainpage.vue

<template>
  <div>
    <Header @myClicked="getValue" />
    <div>
      <component :is="currentTab"></component>
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";
import Header from "./Header.vue";

let currentTab = ref("A");

function getValue(tab) {
  currentTab.value = tab.name;
}

function getTab(tab) {
  currentTab.value = tab.name;
}
</script>

Header.vue

<script setup>
const tabs = [{ name: "A" }, { name: "B" }, { name: "C" }];

const emit = defineEmits(["myClicked"]);
</script>

<template>
  <div class="tabs">
    <button v-bind:class="['tab-button']" 
        @click="$emit('myClicked', tabs[0])">
      A
    </button>
    <button v-bind:class="['tab-button']" 
        @click="$emit('myClicked', tabs[1])">
      B
    </button>
    <button v-bind:class="['tab-button']" 
        @click="$emit('myClicked', tabs[2])">
      C
    </button>
  </div>
</template>

A、B 和 C.vue:

<template>
  <h2>Component A</h2>
</template>
<template>
  <h2>Component B</h2>
</template>
<template>
  <h2>Component C</h2>
</template>

main.js

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

import A from "./components/A.vue";
import B from "./components/B.vue";
import C from "./components/C.vue";

const app = createApp(App);
app.component("A", A);
app.component("B", B);
app.component("C", C);

app.mount('#app')

OCD 稍微清理一下代码。
在 Header.vue 文件中使用 v-for 来简化按钮的创建,并将 name 字段传递到 emit 的方法参数中更改以下 vue 文件:

Header.vue

<script setup>
const tabs = [
  // assuming that in "real" code, 
  // the display name and component name values would likely be different
  { name: "A", compName: "A" },
  { name: "B", compName: "B" },
  { name: "C", compName: "C" },
];

const emit = defineEmits(["myClicked"]);
</script>

<template>
  <div class="tabs">
    <button
      v-for="tab in tabs"
      :key="tab.name"
      @click="$emit('myClicked', tab.compName)"
    >
      {{ tab.name }}
    </button>
  </div>
</template>

Mainpage.vue

<template>
  <div>
    <Header @myClicked="getValue" />
    <div>
      <component :is="currentTab"></component>
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";
import Header from "./Header.vue";

let currentTab = ref("A");

function getValue(tabName) {
  currentTab.value = tabName;
}

function getTab(tab) {
  currentTab.value = tab.name;
}
</script>