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

Vue3组合式API中如何向非嵌套组件传递值(侧边栏场景)

解决Vue3中跨组件侧边栏折叠状态传递问题

方法一:状态提升到共同父组件(推荐轻量场景)

MainLayout是TopBar(包含SideBarButton)和SideBar的共同父组件,将折叠状态放到这里统一管理是最直接的方案:

  1. 修改MainLayout.vue,定义状态与切换方法:
<template>
  <el-header><TopBar @toggle-collapse="toggleCollapse" /></el-header>
  <el-container>
    <el-aside><SideBar :is-collapse="isCollapse" /></el-aside>
    <el-container>
      <!-- 主内容区域 -->
    </el-container>
  </el-container>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import TopBar from './TopBar.vue'
import SideBar from './SideBar.vue'

const isCollapse = ref(false)

const toggleCollapse = () => {
  isCollapse.value = !isCollapse.value
}
</script>
  1. 修改TopBar.vue,透传点击事件:
<template>
  <el-menu-item>
    <SideBarButton @click="$emit('toggle-collapse')" />
  </el-menu-item>
</template>

<script setup lang="ts">
import SideBarButton from './SideBarButton.vue'
defineEmits(['toggle-collapse'])
</script>
  1. 简化SideBarButton.vue,移除内部状态,直接触发事件:
<template>
  <el-button @click="$emit('click')">折叠/展开</el-button>
</template>

<script setup lang="ts">
defineEmits(['click'])
</script>
  1. 修改SideBar.vue,通过Props接收状态:
<template>
  <el-menu
    default-active="2"
    class="el-menu-vertical-demo"
    :collapse="isCollapse"
    @open="handleOpen"
    @close="handleClose"
  >
    <!-- 菜单内容 -->
  </el-menu>
</template>

<script setup lang="ts">
const props = defineProps({
  isCollapse: {
    type: Boolean,
    default: false
  }
})

const handleOpen = () => {}
const handleClose = () => {}
</script>

方法二:修正Provide/Inject用法

你之前使用provide/inject无效,是因为provide的层级错误——不能在SideBarButton中提供状态(SideBar不是它的后代组件),需在共同父组件MainLayout中提供:

  1. 修改MainLayout.vue,提供状态与方法:
<template>
  <el-header><TopBar /></el-header>
  <el-container>
    <el-aside><SideBar /></el-aside>
    <el-container>
      <!-- 主内容区域 -->
    </el-container>
  </el-container>
</template>

<script setup lang="ts">
import { ref, provide } from 'vue'
import TopBar from './TopBar.vue'
import SideBar from './SideBar.vue'

const isCollapse = ref(false)
const toggleCollapse = () => {
  isCollapse.value = !isCollapse.value
}

provide('collapseState', {
  isCollapse,
  toggleCollapse
})
</script>
  1. 修改SideBarButton.vue,注入切换方法:
<template>
  <el-button @click="toggleCollapse">折叠/展开</el-button>
</template>

<script setup lang="ts">
import { inject } from 'vue'

const { toggleCollapse } = inject('collapseState') as {
  toggleCollapse: () => void
}
</script>
  1. 修改SideBar.vue,注入状态:
<template>
  <el-menu
    default-active="2"
    class="el-menu-vertical-demo"
    :collapse="isCollapse"
    @open="handleOpen"
    @close="handleClose"
  >
    <!-- 菜单内容 -->
  </el-menu>
</template>

<script setup lang="ts">
import { inject } from 'vue'

const { isCollapse } = inject('collapseState') as {
  isCollapse: Ref<boolean>
}

const handleOpen = () => {}
const handleClose = () => {}
</script>

方法三:Pinia/Vuex状态管理(适合复杂场景)

若项目中有多组件需要共享这类状态,使用状态管理库更易维护:

  1. 定义Pinia Store:
// stores/collapse.ts
import { defineStore } from 'pinia'

export const useCollapseStore = defineStore('collapse', {
  state: () => ({
    isCollapse: false
  }),
  actions: {
    toggleCollapse() {
      this.isCollapse = !this.isCollapse
    }
  }
})
  1. 修改SideBarButton.vue调用Store方法:
<template>
  <el-button @click="store.toggleCollapse">折叠/展开</el-button>
</template>

<script setup lang="ts">
import { useCollapseStore } from '@/stores/collapse'

const store = useCollapseStore()
</script>
  1. 修改SideBar.vue读取Store状态:
<template>
  <el-menu
    default-active="2"
    class="el-menu-vertical-demo"
    :collapse="store.isCollapse"
    @open="handleOpen"
    @close="handleClose"
  >
    <!-- 菜单内容 -->
  </el-menu>
</template>

<script setup lang="ts">
import { useCollapseStore } from '@/stores/collapse'

const store = useCollapseStore()

const handleOpen = () => {}
const handleClose = () => {}
</script>

内容的提问来源于stack exchange,提问作者H M Sadman Haque

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 04:50:13