vue.jswebvue-events

Reusing method from parent component inside child component


The structure of my app is like this:

Root component(mounted inside main.js(generated with vue-cli)):

<template @parallax-event="parallaxHandler" >
  <div id="app">
  <RepeatingWords></RepeatingWords>
  <NavigationBar></NavigationBar>
  <Intro></Intro>
  <router-view />
  </div>
</template>

The script of this component looks like this:

export default {
  components: {
    RepeatingWords,
    NavigationBar,
    Intro,
  },
  data() {
    return {
      parallaxMovement: Number,
      myWorldParagraph: String,
    }
  },
  methods: {
    parallaxHandler(factor, htmlElementString) {
      this.parallaxMovement = Math.round((window.scrollY / window.outerHeight) * - factor);
      this.myWorldParagraph = htmlElementString;
      console.warn(htmlElementString);
      htmlElementString.style.transform = 'translateX(' + (this.parallaxMovement - 0) + 'px)';
    }
  },
};

Now in my child component(where I want to use this method/ fire this event) I have this:

parallaxScrollEffect() {
    this.$emit('parallax-event', [200, document.querySelector('.some-html-elem')]);
},
mounted() {
    window.addEventListener('scroll', this.parallaxScrollEffect);
},

And so far two things happen:

  1. on Vue DevTools tab Events the events are fired(a lot of them because of scroll),
  2. The arguments have the values I give
  3. No console warn whatsoever,
  4. The element doesn't move and I get no feedback except in the vue tools

I tried:

  1. inside the original method saying factor.target and htmlElementString.target but that didn't work,
  2. removing everything inside the function except console log and passing one single variable with some gibberish string value like:

    this.$emit('parallax-event', ['123123qwe');
    

    which also didn't work.

What am I doing wrong?!

Thank you in advance.

Edit: Fixed small mistake - not parent variables but arguments


Solution

  • I put together an example and faced two problems with your source.

    1. I had to put the "v-on" handler onto the child component and not onto the root template.
    2. The emitted array will be the first parameter of your parallaxHandler.

    According to the VueJS docs:

    Or, if the event handler is a method: Then the value will be passed as the first parameter of that method: https://v2.vuejs.org/v2/guide/components.html#Emitting-a-Value-With-an-Event

    Example App.vue:

    <template >
        <div id="app">
            {{ emittedData }}
            <emit-test @emit-test="setEmittedData" />
        </div>
    </template>
    
    <script>
    import EmitTest from './components/EmitTest.vue';
    
    export default {
        name: 'app',
        data() {
            return {
                emittedData: ''
            };
        },
        components: {
            EmitTest
        },
        methods: {
            setEmittedData(val) {
                this.emittedData = val;
            }
        }
    };
    </script>
    
    <style>
    #app {
        font-family: 'Avenir', Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
        margin-top: 60px;
    }
    </style>
    

    Example EmitTest.vue:

    <template>
        <button @click.prevent="emitToParent">Emit Array</button>
    </template>
    
    <script>
    export default {
        methods: {
            emitToParent() {
                this.$emit('emit-test', ['value 1', 'value 2']);
            }
        }
    };
    </script>
    
    <style lang="scss" scoped>
    </style>
    

    Expected and tested output after a button click: [ "value 1", "value 2" ]