3

I get how to pass data from parent to child with props in a situation like:

<template>
<div>
      <div v-for="stuff in content" v-bind:key="stuff.id">
        <ul>
          <li>
            {{ stuff.items }}
          </li>
        </ul>
      </div>
</div>
</template>

<script>
export default {
  name: stuff,
  props: ['content'],
  data () {
    return {

    }
  }
}
</script>

And then bind the data to the component in the parent component like,

<template>
  <div>
    <stuff v-bind:content="stuffToPass"></stuff>
  </div>
</template>
<script>
import stuff from './stuff.vue';
export default {
  data () {
    return {
      stuffToPass: [
        {id: 1, items: 'foo'},
        {id: 2, items: 'bar'},
        {id: 3, items: 'baz'}
      ]
    }
  },
  components: {
    stuff
  }
}
</script>

But say I have the root component, and I want to pass data to the stuff component, like in the above, but when I have a number of other components like parent > x > y > stuff, and it's still the stuff component that will ultimately be receiving that data, I don't know how to do that.

I heard of provide/inject, but I'm not sure that's the appropriate use, or at least I couldn't get it working.

Then I tried passing props, but then I found myself trying to bind a prop to a component to pass as a prop to a child component and that doesn't sound right, so then I just re-wrote my components in the 'stuff' component, but I feel that's probably re-writing way to much code to be close to reasonable.

7
  • 1
    You should use github.com/vuejs/vuex Commented Jun 3, 2018 at 4:41
  • yes, i am going to be using vuex. the motivation for the question though is that if the 'stuff' component will be used for/in other components aswell, i will need to pass data through a specific parent Commented Jun 3, 2018 at 4:43
  • You can pass data from the parent to x then x to y and in the last y to stuff component. Or you can use any state management library such as redux or flux. Commented Jun 3, 2018 at 4:54
  • 2
    I suggest you see this.$parent, this.$root, provide-inject Commented Jun 3, 2018 at 4:54
  • so then in parent compnent: <script> let dataToPass = { [id: 1, data: 'foo'],..} export default { provide : stuffToPass } Commented Jun 3, 2018 at 5:09

2 Answers 2

2

there are a few possibilities to pass data parent > x > y > stuff

  • props - applicable but you would have to pipe the data through all components...
  • store (vuex) - applicable but could become complicated to handle
  • event bus - the most flexible and direct way

below, a simple example on how to implement the event bus:

// src/services/eventBus.js

import Vue from 'vue';
export default new Vue();

the code from where you want to emit the event:

// src/components/parent.vue

<script>
import EventBus from '@/services/eventBus';

export default {
  ...
  methods: {
    eventHandler(val) {
      EventBus.$emit('EVENT_NAME', val);
    },
  },
  ...
};
</script>

the code for where you want to listen for the event:

// src/components/stuff.vue

<script>
import EventBus from '@/services/eventBus';

export default {
  ...
  mounted() {
    EventBus.$on('EVENT_NAME', val => {
      // do whatever you like with "val"
    });
  },
  ...
};
</script>
Sign up to request clarification or add additional context in comments.

Comments

1

Use watchers or computed properties https://v2.vuejs.org/v2/guide/computed.html

const Stuff = Vue.component('stuff', {
  props: ['content'],
  template: `<div>
      <div v-for="stuff in content" v-bind:key="stuff.id">
        <ul>
          <li>
            {{ stuff.items }}
          </li>
        </ul>
      </div>
</div>`
});

const Adapter = Vue.component('adapter', {
  components: { Stuff },
  props: ['data'],
  template: `<div>
        <Stuff :content="newData"/>
  </div>`,
  data() {
    return {
      newData: []
    };
  },
  created() {
    this.changeData();
  },
  watch: {
    data: {
      deep: true,
      handler: function() {
        this.changeData();
      }
    }
  },
  methods: {
    changeData() {
      this.newData = JSON.parse(JSON.stringify(this.data));
    }
  }
});

const app = new Vue({
  el: '#app',
  components: { Adapter },
  data() {
    return {
      stuffToPass: [
        { id: 1, items: 'foo' },
        { id: 2, items: 'bar' },
        { id: 3, items: 'baz' }
      ]
    };
  },
  methods: {
    addItem() {
      this.stuffToPass.push({ id: this.stuffToPass.length + 1, items: 'new' });
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.1/vue.js"></script>
   <div id="app">
      <button @click="addItem">Add</button>
      <Adapter :data="stuffToPass"/>
    </div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.