Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Eight Methods for Vue Component Communication

Tech 1

1. Parent Component Passing Data to Child Component

  • Import child component in parent component
  • Register the child component
  • Use dynamic binding on child component tag to pass dynamic/static values
  • In child component, use props to receive values passed from parent component

The received values are categorized into reference types and primitive types:

  • Primitive types: String, Number, Boolean, Null
  • Reference types: Array, Object
<!-- Parent Component -->
<template>
  <div>
    <ChildComponent
     :userData="userData" 
     greeting="Hello World"/>
  </div>
</template>

<script>
import ChildComponent from "../components/ChildComponent.vue";
export default {
  name: "ParentView",
  components: {
    ChildComponent,
  },
  data() {
    return {
      userData: {
        statusCode: 200,
        message: "Frontend Learning Community",
      },
    };
  },
};
</script>
<template>
    <div>
        <h1>{{userData.statusCode}}</h1><br>
        <h2>{{userData.message}}</h2>
        <h3>{{greeting}}</h3>
    </div>
</template>

<script>
    export default {
        name:'childcomponent',
        props:{
            userData:Object,
            greeting: [String,Number]
        }
    }
</script>

Since Vue follows unidirectional data flow, child components cannot direct modify parent component values.

2. Child Component Passing Data to Parent Component

Child component emits events using this.$emit('eventName', parameters)

<!-- Parent Component -->
<ChildComponent
     :userData="userData" 
     greeting="Hello World"
     @updateData="handleChildUpdate"/>

<script>
import ChildComponent from "../components/ChildComponent.vue";
export default {
  name: "ParentView",
  components: {
    ChildComponent,
  },
  data() {
    return {
      parentMessage:'I am parent component'
    };
  },
  methods:{
    handleChildUpdate(data){
      this.parentMessage = data
    }
  }
};
</script>
<!-- Child Component -->
<button @click="sendToParent">Update Parent Value</button>

<script>
    export default {
        name:'childcomponent',
        methods:{
            sendToParent(){
                this.$emit('updateData','Data from child component')
            }
        }
    }
</script>

3. Parent Component Accessing Child Component via $refs and $children

$refs:

  • Access DOM elements and component instances to retrieve properties and methods
  • Bind ref attribute to child component and access using this.$refs.refName.childProperty or this.$refs.refName.childMethod()

$children:

  • Returns an array of direct child components
  • Access specific component using this.$children[index].property or this.$children[index].method

Example Child Component

export default {
    name:'childcomponent',
    data() {
        return {
            childData:"I am child component value"
        }
    },
    props:{
        userData:Object,
        greeting: [String,Number]
    },
    methods:{
        getChildValue(){
            console.log('Child method called')
        }
    }
}

Using refs

<template>
  <div>
    <ChildComponent
      ref="childRef"
    />
  </div>
</template>

<!-- Access child component properties and methods -->
console.log(this.$refs.childRef.childData)
this.$refs.childRef.getChildValue()

Using $children

// Access child component properties and methods via $children
this.$children[0].getChildValue();
console.log(this.$children[0].childData);

4. Child Component Accessing Parent Component via $parent

export default {
    name:'childcomponent',
    created(){
        console.log(this.$parent.userData);
        this.$parent.getParentData();
    }
}

5. $attrs and $listeners for Parent Component Properties and Methods (Used in Nested Components)

$attrs: Contains attribute bindings from parent scope that are not recognized as props (except class and style). Can be passed to internal components using v-bind="$attrs". When no props are declared, it contains all parent scope bindings (except class and style).

$listeners: Contains event listeners from parent scope (excluding .native modifiers). Can be passed to internal components using v-on="$listeners". It's an object containing all event listeners bound to the component.

Use Case: Used in multi-level nested components to avoid Vuex for data handling.

Parent Component

<template>
    <div>
        <NestedChild  
        :status="status" 
        :header="header"
        @fetchData="handleFetch" />
    </div>
</template>

<script>
import NestedChild from "../components/NestedChild.vue";
export default {
    name:'maincomponent',
    data(){
        return {
            header:'Main component',
            status: true
        }
    },
    methods:{
        handleFetch(){
            console.log(this.header);
        }
    },
    components:{
        NestedChild
    }
}
</script>

Intermediate Component

<template>
  <div>
    <h1>Nested Child Component</h1>
    <DeepChild v-bind="$attrs" v-on="$listeners"/>
  </div>
</template>

<script>
import DeepChild from "../components/DeepChild";
export default {
  name: "nestedchild",
  props: ["header"],
  components: {
    DeepChild,
  },
  created() {
    console.log(this.$attrs);  //{status: true}
    console.log(this.$listeners); // {fetchData: ƒ}
  },
};
</script>

Deeply Nested Component

<template>
    <div>
        <h1>Deep Child Component</h1>
    </div>
</template>

<script>
    export default {
        name:'deepchild',
        created(){
            console.log('Deep Child Initiated')
            console.log(this.$attrs) //{status: true}
            console.log(this.$listeners) // {fetchData: ƒ}
        }
    }
</script>

6. Cross-Component Communication

Create a JavaScript file importing Vue, export a Vue instance, bind events using $emit, and listen with $on to achieve global component data sharing.

Use Cases:

Suitable for parent-child, child-parent, sibling, and cross-level component communication.

event-bus.js

import Vue from 'vue'

export default new Vue()

Component A

<template>
    <div>  
        <button @click="broadcastValue">Broadcast</button>
    </div>
</template>

<script>
import EventBus from '../util/event-bus.js';
export default {
    name:'componenta',
    data(){
        return {
            message:'Component A message',
            isActive: false
        }
    },
    methods:{
        broadcastValue(){
            EventBus.$emit("receiveMessage", this.message);
        }
    }
}
</script>

Component C

<template>
  <div>
    <h1>Component C</h1>
    <h1>{{ receivedMessage }}</h1>
  </div>
</template>

<script>
import EventBus from "../util/event-bus";
export default {
  name: "componentc",
  data() {
    return {
      receivedMessage: "default",
    };
  },
  mounted(){
    EventBus.$on("receiveMessage", (payload) => {
      this.receivedMessage = payload;
      console.log(payload)
    });
  }
};
</script>

7. Vuex

This will be covered in a separate detailed article.

8. provide and inject for Ancestor to Descendant Communication (Unlimited Levels)

These options work together to allow an ancestor component to inject dependencies into all its descendants regardless of depth, remaining active throughout their lifecycle relationship.

provide:

  • An object or function returning an object
  • Contains properties that can be injected into descendants

inject:

  • An array of strings or an object
  • Used in child/descendant components to inject properties provided by ancestors

Use Case:

Easily acheive cross-level access to ancestor component data

// provide
// Object form
provide:{
    sharedValue:'Example data'
}
// Function form
provide(){
    return {
        sharedValue: 'Example data'
    }
}

// inject
inject:['sharedValue']

Ancestor Component

<template>
    <div>
        <h1>Ancestor Component</h1>
        <Descendant />
    </div>
</template>

<script>
import Descendant from '../components/Descendant'
export default {
    name:'ancestor',
    provide(){
        return {
            ancestorValue: 'Ancestor data'
        }
    },
    components:{
        Descendant
    },
    data(){
        return{
            title:'I am ancestor component'
        }
    }
}
</script>

Descendant Component

<template>
    <div>
        <h1>Descendant Component</h1>
    </div>
</template>

<script>
export default {
    name:'descendant',
    inject:['ancestorValue'],
    created(){
        console.log(`${this.ancestorValue} - Accessed in descendant`)
    },
    data(){
        return{
            title:'I am descendant component'
        }
    }
}
</script>
Tags: Vue.js

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.