I recently explored the communication between components using vuejs and vuex. Here is a scenario I encountered:
- The first component is a
menu
- The second component, nested within the first, is a
hamburgerButton
.
In this specific case, when I click the hamburgerButton
, both the button and the menu animate. The code I have implemented ensures that after clicking the button, the menu
transitions with vueTransition and so does the hamburgerButton
. I am also utilizing vuex to manage the state of menuIsOpen
.
However, the issue arises when I click an item in the menu. I want the animation of the hamburgerButton
to be triggered as well.
The animation method for hamburgerButton
, invoked by animButtonHandler()
, is nested within a @click
event. I understand why it is not functioning correctly at the moment, but I am unsure how to link this method to a click event on a parent element (an item in the menu). Therefore, my question is, how can I access a method in a child component from a parent component? Alternatively, is there another effective method to achieve this?
Parent component - menu.vue :
<template>
<div class="menu">
<!-- import hamburgerButton component -->
<hamburger-button></hamburger-button>
<transition v-on:enter="enterMenuHandler" v-on:leave="leaveMenuHandler">
<div class="menu_wrapper" v-if="this.$store.state.menuIsOpen">
<ul class="menu_items">
<li class="menu_item" @click="$store.commit('toggleMenu')">
<router-link class="menu_link" to="/">home</router-link>
<router-link class="menu_link" to="/contact">contact</router-link>
</li>
</ul>
</div>
</transition>
</div>
</template>
<script>
import hamburgerButton from "hamburgerButton.vue";
export default {
components: {
'hamburger-button': hamburgerButton,
},
methods: {
enterMenuHandler(el, done){
TweenLite.fromTo(el, 0.5, {
opacity: '0',
},{
opacity: '1',
onComplete: done
});
},
leaveMenuHandler(el, done){
TweenLite.to(el, 0.5, {
opacity: '0',
onComplete: done
});
},
}
}
</script>
Child component: hamburgerButton.vue :
<template>
<div class="hamburgerButton" @click="animButtonHandler()">
<div class="hamburgerButton_inner" ref="hamburgerButtonInner">
<i class="hamburgerButton_icon></i>
</div>
</div>
</template>
<script>
export default {
methods: {
animButtonHandler (){
// toggle the state of the menu when button is clicked
this.$store.commit('toggleMenu');
const isOpen = this.$store.state.menuIsOpen === true;
// animate the button
TweenLite.to(this.$refs.hamburgerButtonInner, 0.5, {
rotation: isOpen ? "43deg" : '0',
});
},
}
}
</script>
store.js (imported in the main.js) :
let store = new Vuex.Store({
state : {
menuIsOpen : false,
},
mutations: {
toggleMenu(state) {
state.menuIsOpen = !state.menuIsOpen
}
}
});