Vue js:从父组件调用chid方法

时间:2017-12-13 08:18:53

标签: javascript animation methods vue.js

我尝试使用vuejs和vuex与组件进行通信:

  1. 第一个组件是menu
  2. 第二个组件,在第一个组件内,是hamburgerButton
  3. 在目前的情况下,当我点击hamburgerButton时,这个动画和菜单也是如此。使用此代码,在单击按钮后,menu将使用vueTransition和hamburgerButton进行动画处理。请注意,我使用vuex来管理menuIsOpen状态。

    我的问题是当我点击菜单项时,我想要解雇hamburgerButton动画。

    hamburgerButton动画方法,调用animButtonHandler(),封装在@click事件中。实际上我理解为什么它不能正确地知道,但我不知道如何处理这个方法来点击父元素(菜单项)。所以我的问题是,如何从父组件访问子组件的方法?或者是否有另一种解决方法来实现这一目标?

    父组件 - 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>
    

    子组件: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 menu if button clicked
                this.$store.commit('toggleMenu');
                const isOpen = this.$store.state.menuIsOpen === true;
                // anim the button
                TweenLite.to(this.$refs.hamburgerButtonInner, 0.5, {
                    rotation: isOpen ? "43deg" : '0',
                });
            },
        }
    }
    </script>
    

    store.js(在main.js中导入):

    let store = new Vuex.Store({
        state : {
                menuIsOpen : false,
        },
        mutations: {
            toggleMenu(state) {
                state.menuIsOpen = !state.menuIsOpen
             }
        }
    });
    

2 个答案:

答案 0 :(得分:1)

我添加了事件总线的基本示例。你现在可以将它与之比较,并做出明智的改变。

如果发现任何困难,请发表评论。

<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/vue@2.1.10/dist/vue.min.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div id="app">
    <h2>event bus</h2>    
    <button @click="callChildAnimateMethod"> Button On Parent Call Child </button>     
    <childcmp><childcmp />
  </div>
  <script>  
  var EventBus = new Vue();
  
  Vue.component('childcmp', {
    template: `<div>child demo - {{ message }}</div>`,
    data: function() {
      return {
        message: 'hello'
      }
    },
    mounted: function() {
      // listen for event
      EventBus.$on('animate', this.animButtonHandler);
    },
    destroyed: function(){
      // remove listener
      EventBus.$off('animate', this.animButtonHandler);
      
    },
    methods: {
      animButtonHandler: function() {
        console.log('this is child method');
        this.message = 'I am changed.'
      }
    }
  });

   new Vue({
      el: '#app',
      data: function() {
        return {
          
        }
      },
      methods: {
        callChildAnimateMethod: function() {          
          EventBus.$emit('animate');
        }
      }

    });
  </script>
</body>
</html>

更新

您需要定义 EventBus

  

eventbus.js

import Vue from 'vue';
const EventBus = new Vue();
export default EventBus;
  

父组件 - menu.vue

import EventBus from './eventbus.js'
... your code
  

子组件:hamburgerButton.vue:

import EventBus from './eventbus.js'
... your code

现在EventBus将可用于您的代码。

答案 1 :(得分:1)

由于您想知道如何使用您的代码集成事件总线,因此它是:

创建一个只是空vue实例的事件总线

将它添加到main.js文件中或将其外包到一个完整的文件中;

<强> main.js

uname -r

<强> menu.vue

H.but(3) = uicontrol('Units','normalized', ...

    'BackgroundColor',[1 0.7 1], ...
    'Callback','MyFunction(''Reset'');', ...
    'FontSize',12, ...
    'Position',[0.04 0.54 0.1 0.05 ], ...
    'String','Reset');

case 'Reset'
clear all % Is not working and I think that isn't that I expect
set(findobj(H.fig,'style','edit', '-or','style','text'),'string','') % H is a global variable. This trial don't give the default value, it just clear certain boxes

在创建的钩子中的事件总线上设置一个事件监听器,并在每个export const EventBus = new Vue(); 事件上执行动画

<强> hamburgerButton.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="toggleMenu">
                        <router-link class="menu_link" to="/">home</router-link>
                        <router-link class="menu_link" to="/contact">contact</router-link>
                    </li>
                </ul>w
            </div>
        </transition>
    </div>
</template>

<script>
import hamburgerButton from "hamburgerButton.vue";
import {EventBus} from './path/to/main.js' //or a path to file where you exported your EventBus

export default {
    components: {
        'hamburger-button': hamburgerButton,
    },
    methods: {
        toggleMenu(){
            this.$store.commit('toggleMenu');
            EventBus.$emit('animate-hamburger-btn');
        },
        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>