Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Eight Methods for Vue Component Communication

Tech Apr 27 10

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...

SBUS Signal Analysis and Communication Implementation Using STM32 with Fus Remote Controller

Overview In a recent project, I utilized the SBUS protocol with the Fus remote controller to control a vehicle's basic operations, including movement, lights, and mode switching. This article is aimed...

Comprehensive Guide to Hive SQL Syntax and Operations

This article provides a detailed walkthrough of Hive SQL, categorizing its features and syntax for practical use. Hive SQL is segmented into the following categories: DDL Statements: Operations on...

Leave a Comment

Anonymous

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