Home > Blockchain >  Vue2 use $ref to load data from child component and put into parent component's data
Vue2 use $ref to load data from child component and put into parent component's data

Time:12-15

In Vue2 I'm trying to access child components' data and then put into parent component's data without triggering an event. In the following example I want to save count:20 into parent component, please tell me if there's any mistake, thanks!

Child Component

<template>
  <div></div>
</template> 
<script>
export default {
  data() {
    return {
      count: 20,
    };
  },
};
</script>

Parent Component

<template>
  <div>
    <child ref="child1"></child>
    {{count}}
</div>
</template> 

<script> import child from './child.vue' 
export default { 
  components: {
    child
  }, 
  data() {
    return{
      count:this.$refs.child1.count
    }
  },
} 
</script>

warn message in VScode

Property 'count' does not exist on type 'Vue | Element | Vue[] | Element[]'. Property 'count' does not exist on type 'Vue'.

warn message in browser

[Vue warn]: Error in data(): "TypeError: undefined is not an object (evaluating 'this.$refs.child1')"

CodePudding user response:

Let me preface with I would recommend using the Vue framework as intended. So passing data from a child to the parent should be done with $emit or using a vuex store for centralized state management.

With that out of the way you will want to wait until the parent component is mounted to set the count data attribute.

Child

<template>
  <div></div>
</template> 
<script>
export default {
  data() {
    return {
      count: 20,
    };
  },
};
</script>

Parent

<template>
  <div>
    <child ref="child1"></child>
    {{ count }}
  </div>
</template>

<script>
import Child from "./components/Child";

export default {
  components: {
    Child
  },
  data() {
    return{
      count: 0
    }
  },
  mounted () {
    this.count = this.$refs.child1.count
  }
};
</script>

This will work, however it WILL NOT BE reactive. This can all be greatly simplified AND made reactive with the following changes:

Child

<template>
  <div></div>
</template> 
<script>
export default {
  data() {
    return {
      count: 20,
    };
  },
  watch: {
    count (currentValue) {
      this.$emit('update', currentValue);
    }
  },
  beforeMount () {
    this.$emit('update', this.count)
  }
};
</script>

Parent

<template>
  <div>
    <child @update="count = $event"></child>
    {{ count }}
  </div>
</template>

<script>
import Child from "./components/Child";

export default {
  components: {
    Child
  },
  data() {
    return{
      count: 0
    }
  }
};
</script>

Quick link to show a working example: https://codesandbox.io/s/interesting-kalam-et0b3?file=/src/App.vue

  • Related