Direct access between instances of Vue components

Front words

Sometimes a parent component is required to access a child component, a child component to access a parent component, or a child component to access the root component. In the component instance, Vue provides the corresponding properties, including $parent, $children, $refs and $root, which are mounted on the component's this. This article details direct access between instances of Vue components

 

$parent

$parent represents an instance of the parent component, which is read-only

Here is a simple example

<div id="example">
  <parent-component></parent-component>
</div>
<template id="parent-component">
  <div class="parent">
    <h3>I am the parent component</h3>
    <input v-model="parentMsg">
    <p>{{parentMsg}}</p>
    <child-component></child-component>    
  </div>
</template>
<template id="child-component">
  <div class="child">
    <h3>I am a subcomponent</h3>
    <p>{{msg}}</p>
    <button v-on:click="showData">Display parent component data</button>    
  </div>
</template>
<script>
// register
Vue.component('parent-component', {
  template: '#parent-component',
  data(){
    return{
      parentMsg:'I am the data of the parent component'
    }
  },
  components:{
    'child-component':{
      template:'#child-component',
      data(){
        return{
          msg:''
        }
      },
      methods:{
        showData(){
          this.msg = this.$parent.parentMsg;
        }
      }
    }
  }
})
// Create a root instance
new Vue({
  el: '#example'
})
</script>

 

$root

$root represents the root Vue instance of the current component tree. If the current instance does not have a parent instance, the instance will be its own. This property is read-only

<div id="example">
  <h3>I am the root component</h3>
    <input v-model="rootMsg">
    <p>{{rootMsg}}</p>  
  <parent-component></parent-component>
</div>
<template id="parent-component">
  <div class="parent">
    <h3>I am the parent component</h3>
    <input v-model="parentMsg">
    <p>{{parentMsg}}</p>
    <child-component></child-component>    
  </div>
</template>
<template id="child-component">
  <div class="child">
    <h3>I am a subcomponent</h3>
    <p>
      <button v-on:click="showRootData">Display root component data</button><span>{{rootMsg}}</span>
    </p>      
    <p>
      <button v-on:click="showParentData">Display parent component data</button><span>{{parentMsg}}</span>
    </p>
  </div>
</template>
<script>
// register
Vue.component('parent-component', {
  template: '#parent-component',
  data(){
    return{
      parentMsg:'I am the data of the parent component'
    }
  },
  components:{
    'child-component':{
      template:'#child-component',
      data(){
        return{
          parentMsg:'',
          rootMsg:''
        }
      },
      methods:{
        showParentData(){
          this.parentMsg = this.$parent.parentMsg;
        },
        showRootData(){
          this.rootMsg = this.$root.rootMsg;
        },        
      }
    }
  }
})
// Create a root instance
new Vue({
  el: '#example',
  data:{
    rootMsg:'I am the root component data'
  }
})
</script>

 

$children

$children represents a direct subcomponent of the current instance. It should be noted that $children does not guarantee order or responsiveness. If you're trying to use $children for data binding, consider using an array with v-for to generate subcomponents, and using Array as the real source

<div id="example">
  <parent-component></parent-component>
</div>
<template id="parent-component">
  <div class="parent">
    <h3>I am the parent component</h3>
    <button @click="getData">Getting subcomponent data</button>
    <br>
    <div v-html="msg"></div>
    <child-component1></child-component1> 
    <child-component2></child-component2>   
  </div>
</template>
<template id="child-component1">
  <div class="child">
    <h3>I am a sub-component</h3>
    <input v-model="msg">
    <p>{{msg}}</p>
  </div>
</template>
<template id="child-component2">
  <div class="child">
    <h3>I am subcomponent 2</h3>
    <input v-model="msg">
    <p>{{msg}}</p>
  </div>
</template>
<script>
// register
Vue.component('parent-component', {
  template: '#parent-component',
  data(){
    return{
      msg:'',
    }
  },
  methods:{
    getData(){
      let html = '';
      let children = this.$children;
      for(var i = 0; i < children.length;i++){
        html+= '<div>' + children[i].msg + '</div>';
      }
      this.msg = html;
    }
  },
  components:{
    'child-component1':{
      template:'#child-component1',
      data(){
        return{
          msg:'',
        }
      },
    },
    'child-component2':{
      template:'#child-component2',
      data(){
        return{
          msg:'',
        }
      },
    }, 
  }   
})
// Create a root instance
new Vue({
  el: '#example',
})
</script>

 

$refs

When the number of components is large, it is difficult to remember the order and location of each component. It is not convenient to access subcomponents by serial number.

Using ref attributes on subcomponents, you can specify an index ID for subcomponents:

<child-component1 ref="c1"></child-component1>
<child-component2 ref="c2"></child-component2>

In the parent component, an instance of the child component is accessed through the $refs. index ID

this.$refs.c1
this.$refs.c2
<div id="example">
  <parent-component></parent-component>
</div>
<template id="parent-component">
  <div class="parent">
    <h3>I am the parent component</h3>
    <div>
      <button @click="getData1">Getting subcomponents c1 Data</button>
      <p>{{msg1}}</p>
    </div>
    <div>
      <button @click="getData2">Getting subcomponents c2 Data</button>
      <p>{{msg2}}</p>
    </div>
    <child-component1 ref="c1"></child-component1> 
    <child-component2 ref="c2"></child-component2>   
  </div>
</template>
<template id="child-component1">
  <div class="child">
    <h3>I am a sub-component</h3>
    <input v-model="msg">
    <p>{{msg}}</p>
  </div>
</template>
<template id="child-component2">
  <div class="child">
    <h3>I am subcomponent 2</h3>
    <input v-model="msg">
    <p>{{msg}}</p>
  </div>
</template>
<script>
// register
Vue.component('parent-component', {
  template: '#parent-component',
  data(){
    return{
      msg1:'',
      msg2:'',
    }
  },
  methods:{
    getData1(){
      this.msg1 = this.$refs.c1.msg;
    },
    getData2(){
      this.msg2 = this.$refs.c2.msg;
    },    
  },
  components:{
    'child-component1':{
      template:'#child-component1',
      data(){
        return{
          msg:'',
        }
      },
    },
    'child-component2':{
      template:'#child-component2',
      data(){
        return{
          msg:'',
        }
      },
    }, 
  }   
})
// Create a root instance
new Vue({
  el: '#example',
})
</script>

 

summary

Although vue provides direct access to component instances in the above way, it is not recommended to do so. This can lead to tight coupling between components and difficult to understand their own state, so use it as much as possible. props,Custom Events as well as Content distribution slot To transfer data

Keywords: Javascript Vue

Added by The Little Guy on Sun, 02 Jun 2019 22:45:25 +0300