1

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

r.gjoni
  • 45
  • 7

1 Answers1

1

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" ]

tony19
  • 125,647
  • 18
  • 229
  • 307
  • 1
    I had to use the first(and only) parameter like an array: factor[0], factor[1] and it worked like a charm! Thank you very much! It's a shame though that we can't use more than one parameter like normal functions/methods. – r.gjoni Dec 12 '19 at 21:37
  • 1
    An alternative may be to use destructuring. Like emitting an object "{prop1: val1, prop2: val2}" and using a method signature like "method({ prop1, prop2})". – Peter Duchon Dec 12 '19 at 21:48