I have a MainLayout , SideBar Component and a TopBar Component. I placed a SideBarButton Component on the the TopBar Component, which when clicked should toggle the sidebar.
How do i pass the ref variable of SideBarButton to the SideBar Component?
MainLayout.vue
<template>
<el-header><TopBar /> </el-header>
<el-container>
<el-aside ><SideBar /> </el-aside>
<el-container>
</template>
TopBar.vue
<template>
<el-menu-item>
<SideBarButton />
</el-menu-item>
</template>
SideBarButton.vue
<template>
<el-button @click="toggleCollapsed"/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const isCollapse = ref(false)
const toggleCollapsed = (e) => {
isCollapse.value = !isCollapse.value;
};
</script>
SideBar.vue
<template>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
:collapse="isCollapse"
@open="handleOpen"
@close="handleClose"
>
</template>
<script setup lang="ts">
</script>
How do i get the value of isCollapse in this SideBar Component? I have tried for inject/provide but it didnt work. Also the SideBarButton Component and SideBarComponent are not parent and child components, so Props do not work.
Emit the value from SideBarButton to TopBar, re-emit to MainLayout, then use the value to set a prop on SideBar
SideBarButton.vue
<script setup lang="ts">
const emit = defineEmits(['toggleCollapsed'])
const toggleCollapsed = (e) => {
isCollapse.value = !isCollapse.value;
emit('toggleCollapsed', isCollapse.value)
};
</script>
TopBar.vue
<template>
<el-menu-item>
<SideBarButton @toggleCollapsed="$emit('toggleCollapsed', $event)" />
</el-menu-item>
</template>
MainLayout.vue
<template>
<el-header>
<TopBar @toggleCollapsed="isCollapse = $event" />
</el-header>
<el-container>
<el-aside>
<SideBar :isCollapse="isCollapse" />
</el-aside>
<el-container>
</template>
<script setup>
const isCollapse = ref(false)
</script>
Sidebar.vue
<script setup lang="ts">
defineProps({
isCollapse: {
default: false
}
})
</script>
New in Vue 3.4, the defineModel macro can now be used with v-model. It's basically still doing the same job as setting up props and emits under the hood, but less code.
MainLayout.vue
<template>
<el-header>
<TopBar v-model="isCollapse" />
</el-header>
<el-container>
<el-aside>
<SideBar :isCollapse="isCollapse" />
</el-aside>
<el-container>
</template>
<script setup>
const isCollapse = ref(false)
</script>
TopBar.vue
<template>
<el-menu-item>
<SideBarButton v-model="isCollapse" />
</el-menu-item>
</template>
<script setup>
const isCollapse = defineModel()
</script>
SideBarButton.vue
<template>
<el-button @click="value = !value"/>
</template>
<script setup lang="ts">
const value = defineModel()
</script>
SideBar.vue
(same as Method 1)
<script setup lang="ts">
defineProps({
isCollapse: {
default: false
}
})
</script>
It's not clear in your question whether SideBar.vue also needs to be able to set the value of isCollapse
, but my code in both methods assumes it does not. If it does, you can use the same strategies again with emitting the change back up to MainLayout or using v-model/defineModel again with SideBar.