0

Coming from a React development environment, I'm challenging myself to learn some Vue at the moment. However, I'm stuck with some problems to pass data along as props between components.

My objective is to display strings out of a list as

elements, which later I'll animate with transitions. For this, I created a Vue project using the Vue Cli and additional libraries include only Bootstrap and Router.

I just can't make this to work...

So I have a main.js containing my paths and :

new Vue({
  router,
  data: {
    listOfStrings: ['test1 test1', 'test2', 'test3']
  },
  render: h => h(App),

}).$mount('#app')

I also have a Home.vue containing a region with a big image, where I want to put the sentences from the list.

<template>
    <div class="homelander">
        <div class="container">
            <TextHome/>
        </div>
    </div>
</template>
<script>
import TextHome from '../components/TextHome.vue'
export default {
    name: 'Home',
    components: {
    TextHome
    }
</script>
}

And finally, I have a TextHome component, which I actually would like to reuse by being able to pass the list containing the strings as props.

TextHome.vue

<div v-for="item in listOfStrings" v-bind:key="item">
   <p>{{item}}</p>
</div>

It doesn't matter what I try, the list is, undefined, or I get "Property or method "listOfStrings" is not defined on the instance but referenced during render.", or even an error due to keys missing for each char from the string... So, yeah.. I'm very confused... If anyone could shed some light on this mess, I would be grateful.

4 Answers 4

1

Parent vm is not available to children in Vue. You have to pass it down. Basically, you can chose between two patterns:

  • pass them down props to children instances <child-component :some-prop="parentMethod"> - you also have to define someProp as component prop in child-component)
  • use Vuex, (keep all your data into the store and import exactly what you need exactly where you need it, using mapGetters).

In your case, it makes sense to use first option, but if you find yourself having to pass down data 3 or 4 levels, having to also pass actions up from children to parents in a similar fashion, you probably should consider using Vuex.

Also, data cannot be an object in Vue. Vue sets reactive setters/getters on data at runtime and, if your data is an object, it will error out. You either don't define it at all, or you define it as a function returning an object.

All the keys defined on data are going to be reactive (= watched for changes). Any change in their values will result in the component being updated/re-rendered. Valid examples of data:

data() {
  return {/* your data here */ }
}

data: () => ({ /* your data here */ })

Last, but not least, if there is no good reason (i.e: it needs to be shared with some other component) for listOfStrings to live in the parent, don't define it there. You should set it as data exactly where you need it, which is in the child component:

Vue.config.productionTip = false;
Vue.config.devtools = false;

Vue.component('text-home', { 
  template: `<div>
    <p v-for="(item, key) in listOfStrings" :key="key" v-text="item" />
  </div>`,
  data: () => ({
    listOfStrings: ['string 1', 'string 2', 'string 3']
  })
});

new Vue({
  el: '#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div class="homelander">
        <div class="container">
            <text-home />
        </div>
    </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for the detailed explanation. I think I'm starting to get the feeling of it. :)
1

You should have data in parent component as function and send that data to the child component as props, below is code snippet:

<template>
    <div class="homelander">
        <div class="container">
            <TextHome :listOfStrings="listOfStrings"/>
        </div>
    </div>
</template>
<script>
import TextHome from '../components/TextHome.vue'
export default {
    name: 'Home',
    components: {
    TextHome
    },
    data : function {
     return {
        listOfStrings: ['test1 test1', 'test2', 'test3']
      }
    }
</script>
}

and then in child component you must access that data through props assigned as below:

<template>
    <div v-for="item in listOfStrings" v-bind:key="item">
      <p>{{item}}</p>
    </div>
</template>
<script>
export default {
    name: 'TextHome',
    props: ["listOfStrings"]
</script>
}

Comments

0

Could it be that you're missing a closing parenthesis in the export block?

1 Comment

Nope.. it was just a copy paste issue
0

new Vue is just a instance of Vue Object and TextHome.vue is a component of Vue instance ,it can't use data from other components(Because of vue restrictions?).

you can use prop to pass data

or accessing the Root Instance

or Dependency Injection

or use Vue.prototype to define a global property in main.js.

or vuex

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.