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

如何在Home.vue按钮点击时触发全局组件music-player的togglePlayback方法?

解决方案:跨组件触发音乐播放器方法

针对你的需求,这里提供两种适合Vue新手的实现方案,分别对应简单场景和复杂场景:


方案1:事件总线(mitt库)

适合简单的跨组件通信场景,步骤清晰易上手。

步骤1:安装mitt库

Vue3移除了原生的事件总线API,推荐使用mitt实现:

npm install mitt

步骤2:创建事件总线文件

在src/utils目录下新建eventBus.js:

import mitt from 'mitt';
const emitter = mitt();
export default emitter;

步骤3:修改music-player.vue监听事件

在组件中添加事件监听,触发现有togglePlayback方法,并在组件卸载时清理监听:

<button class="btn bg-[#a47551] hover:text-gray-50 p-3 shadow-xl"  @click="togglePlayback">
   <span class="material-symbols-outlined">
      {{ isPlaying ? "pause" : "play_arrow" }}
    </span>
</button>

<script>
import { onMounted, ref, onUnmounted } from "vue";
import emitter from '@/utils/eventBus'; // 引入事件总线

export default {
    setup() {
        const audio = new Audio();
        const isPlaying = ref(false);
        
        function togglePlayback() {
            if (isPlaying.value) {
                pausePlayback();
            } else {
                playPlayback();
            }
        }

        function playPlayback() {
            if (!isPlaying.value) {
                audio.play();
                isPlaying.value = true;
            }
        }

        function pausePlayback() {
            if (isPlaying.value) {
                audio.pause();
                isPlaying.value = false;
            }
        }

        function handlePlaybackStart() {
            isPlaying.value = true;
        }

        function handlePlaybackPause() {
            isPlaying.value = false;
        }

        onMounted(() => {
            audio.src = "@/assets/song/1.mp3"; // 改用@指向src目录,路径更可靠
            audio.loop = true;
            audio.addEventListener("play", handlePlaybackStart);
            audio.addEventListener("pause", handlePlaybackPause);
            // 监听toggle-music事件,触发togglePlayback
            emitter.on('toggle-music', togglePlayback);
        });

        onUnmounted(() => {
            // 移除事件监听,避免内存泄漏
            emitter.off('toggle-music', togglePlayback);
            // 清理audio事件监听
            audio.removeEventListener("play", handlePlaybackStart);
            audio.removeEventListener("pause", handlePlaybackPause);
        });

        return {
            togglePlayback,
            isPlaying,
        };
    },
};
</script>

步骤4:修改Home.vue触发事件

在按钮点击方法中发送事件:

<button class="btn bg-[#a47551] text-gray-50" @click="lihatUndangan">Lihat undangan</button>

<script>
import { ref } from 'vue';
import { useRouter } from "vue-router";
import emitter from '@/utils/eventBus'; // 引入事件总线

export default {
  data() {
    return {
      namaTamu: '',
      isLoading: true // 补充声明isLoading,避免报错
    };
  },
  mounted() {
    const namaTamu = localStorage.getItem('namaTamu');

    if (!namaTamu) {
      const namaInput = window.prompt('Masukkan nama:');
      
      if (namaInput && namaInput.trim() !== '') {
        localStorage.setItem('namaTamu', namaInput);
        this.namaTamu = namaInput;
      } else {
        this.namaTamu = 'Tamu Undangan';
      }
    } else {
      this.namaTamu = namaTamu;
    }

    setTimeout(() => {
      this.isLoading = false;
    }, 500);
  },
  setup() {
    const router = useRouter();

    function lihatUndangan() {
      emitter.emit('toggle-music'); // 发送事件触发音乐切换
      router.push('/welcome');
    }

    return {
      lihatUndangan
    };
  }
};
</script>

方案2:Pinia状态管理(推荐复杂场景)

如果后续需要在多个组件中控制音乐播放状态,用Pinia管理状态更规范、可维护。

步骤1:安装Pinia

npm install pinia

步骤2:挂载Pinia到Vue应用

修改main.js:

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';

const app = createApp(App);
app.use(createPinia());
app.mount('#app');

步骤3:创建音乐状态仓库

在src/stores目录下新建musicStore.js:

import { defineStore } from 'pinia';

export const useMusicStore = defineStore('music', {
  state: () => ({
    audio: new Audio(),
    isPlaying: false
  }),
  actions: {
    togglePlayback() {
      this.isPlaying ? this.pausePlayback() : this.playPlayback();
    },
    playPlayback() {
      if (!this.isPlaying) {
        this.audio.play();
        this.isPlaying = true;
      }
    },
    pausePlayback() {
      if (this.isPlaying) {
        this.audio.pause();
        this.isPlaying = false;
      }
    },
    initAudio() {
      this.audio.src = "@/assets/song/1.mp3";
      this.audio.loop = true;
      // 绑定audio事件同步状态
      this.audio.addEventListener("play", () => {
        this.isPlaying = true;
      });
      this.audio.addEventListener("pause", () => {
        this.isPlaying = false;
      });
    }
  }
});

步骤4:重构music-player.vue使用Pinia

<button class="btn bg-[#a47551] hover:text-gray-50 p-3 shadow-xl"  @click="togglePlayback">
   <span class="material-symbols-outlined">
      {{ isPlaying ? "pause" : "play_arrow" }}
    </span>
</button>

<script>
import { onMounted } from "vue";
import { useMusicStore } from '@/stores/musicStore';

export default {
    setup() {
        const musicStore = useMusicStore();
        
        onMounted(() => {
            musicStore.initAudio();
        });

        return {
            togglePlayback: musicStore.togglePlayback,
            isPlaying: musicStore.isPlaying,
        };
    },
};
</script>

步骤5:修改Home.vue调用Pinia方法

<button class="btn bg-[#a47551] text-gray-50" @click="lihatUndangan">Lihat undangan</button>

<script>
import { ref } from 'vue';
import { useRouter } from "vue-router";
import { useMusicStore } from '@/stores/musicStore';

export default {
  data() {
    return {
      namaTamu: '',
      isLoading: true
    };
  },
  mounted() {
    const namaTamu = localStorage.getItem('namaTamu');

    if (!namaTamu) {
      const namaInput = window.prompt('Masukkan nama:');
      
      if (namaInput && namaInput.trim() !== '') {
        localStorage.setItem('namaTamu', namaInput);
        this.namaTamu = namaInput;
      } else {
        this.namaTamu = 'Tamu Undangan';
      }
    } else {
      this.namaTamu = namaTamu;
    }

    setTimeout(() => {
      this.isLoading = false;
    }, 500);
  },
  setup() {
    const router = useRouter();
    const musicStore = useMusicStore();

    function lihatUndangan() {
      musicStore.togglePlayback(); // 直接调用仓库方法
      router.push('/welcome');
    }

    return {
      lihatUndangan
    };
  }
};
</script>

额外提示

  • 音频路径建议使用@/assets/song/1.mp3,@在Vue项目中默认指向src目录,避免相对路径出错
  • 使用事件总线时必须在组件卸载时移除监听,防止内存泄漏
  • 如果只是简单的一次触发,事件总线足够;如果需要多组件共享播放状态,优先选Pinia

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:12:54