代码之家  ›  专栏  ›  技术社区  ›  BrownBe

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

  •  1
  • BrownBe  · 技术社区  · 7 年前

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

    1. 第一个组件是 menu
    2. 第二个组件位于第一个组件内部,是 hamburgerButton .

    在当前的情况下,当我单击 汉堡按钮 ,这一个是动画,菜单也是。使用此代码,单击按钮后 菜单 使用vueTransition和 汉堡按钮 也请注意,我使用vuex管理 menuIsOpen 状态

    我的问题是,当我单击菜单项时,我想 汉堡按钮 动画

    汉堡按钮 动画方法,调用 animButtonHandler() ,封装在 @click 事件实际上,我知道为什么它不能正常工作,但我不知道如何在单击父元素(菜单项)时处理此方法。所以我的问题是,如何从父组件访问子组件的方法?或者是否有其他解决方法来实现这一点?

    父组件-菜单。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>
    

    子组件:汉堡按钮。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>
    

    百货商店js(在main.js中导入):

    let store = new Vuex.Store({
        state : {
                menuIsOpen : false,
        },
        mutations: {
            toggleMenu(state) {
                state.menuIsOpen = !state.menuIsOpen
             }
        }
    });
    
    2 回复  |  直到 3 年前
        1
  •  1
  •   Hardik Satasiya    7 年前

    我添加了事件总线的基本示例。现在,您可以将其与进行比较,并像wise一样进行更改。

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

    <!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>

    使现代化


    您需要定义 事件总线

    事件总线。js公司

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

    父组件-菜单。vue

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

    子组件:汉堡按钮。vue:

    从“”导入EventBus/事件总线。js'
    ... 您的代码
    

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

        2
  •  1
  •   Vamsi Krishna    7 年前

    由于您想知道如何将事件总线与您的代码集成,下面是:

    创建一个仅为空vue实例的事件总线

    将其添加到主菜单中。js文件或将其外包到spererate文件中;

    主要的js公司

    export const EventBus = new Vue();
    

    菜单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> 
    

    在创建的挂钩中的事件总线上设置事件侦听器,并在每个 animate-hamburger-btn 事件

    汉堡按钮。vue

    <template>
        <div class="hamburgerButton" @click="animButtonHandler()">
            <div class="hamburgerButton_inner" ref="hamburgerButtonInner">
                <i class="hamburgerButton_icon></i>
            </div>
        </div>
    </template>
    
    <script>
    import {EventBus} from './path/to/main.js' //or a path to file where you exported your EventBus
    export default {
        created(){
            EventBus.$on('animate-hamburger-btn', () => {
                this.animateBtn();
            });
        }.
        methods: {
            animButtonHandler (){
                // toggle the state of menu if button clicked
                this.$store.commit('toggleMenu');
                this.animateBtn();
            },
            animateBtn(){
                const isOpen = this.$store.state.menuIsOpen === true;
                // anim the button
                TweenLite.to(this.$refs.hamburgerButtonInner, 0.5, {
                    rotation: isOpen ? "43deg" : '0',
                });
            }
        }
    }
    </script>