Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Vue 2 Component Architecture: Registration, Lifecycle, and State Communication

Tech 1

Every Vue component resides in a .vue file, encapsulating markup, logic, and styles.

<template>
  <div class="main-wrapper"></div>
</template>

<script>
export default {};
</script>

<style lang="scss" scoped>
/* Scoped styles prevent leakage */
</style>

The <template> acts as an invisible wrapper and permits only a single root element. The <script> exports an object containing data, methods, and configurations. The <style> supports pre-processors and scoping via the scoped attribute.

Component Registration

Local Registration: Ideal for components used sparingly. Import the component and declare it within the components option.

<template>
  <div>
    <NavBar />
    <SidePanel />
  </div>
</template>

<script>
import NavBar from '@/components/NavBar.vue';
import SidePanel from '@/components/SidePanel.vue';

export default {
  components: {
    NavBar,
    SidePanel
  }
}
</script>

Global Registration: Suitable for frequently reused components. Define them once in the entry point (main.js).

import Vue from 'vue';
import App from './App.vue';
import GlobalButton from '@/components/GlobalButton.vue';

Vue.component('BaseButton', GlobalButton);

new Vue({
  render: h => h(App)
}).$mount('#app');

Usage remains standard: <BaseButton />.

Custom Attributes (Props)

Props enable component reusability by allowing data to be passed from outside. They are strictly read-only; to manipulate a prop, transfer its value to a reactive data property.

Array Syntax: Lacks type checking and default values.

export default {
  props: ['initialValue', 'label']
}

Object Syntax: Provides validation, types, and defaults.

export default {
  props: {
    label: {
      type: String,
      default: 'Default Label',
      required: true
    },
    initialValue: {
      type: Number,
      default: 0
    }
  }
}

When passing dynamic values, use v-bind. For instance, :count="10" passes a number, whereas count="10" passes a literal string.

Style Scoping and Deep Selectors

Adding the scoped attribute ensures styles apply only to the current component by adding unique data attributes to DOM elements. To affect child component styles from a parent, use deep selectors like ::v-deep.

<style lang="scss" scoped>
::v-deep .child-element {
  color: crimson;
}
</style>

Component Lifecycle

A component undergoes creation, mounting, updating, and destruction. Lifecycle hooks are built-in methods triggered automatically during these phases.

export default {
  created() {
    console.log('Component instance created');
  }
}

Data Communication

Parent to Child: Data flows downwrad via props. The parent binds data to the child's custom attribute.

Parent Component:

<template>
  <ProfileCard :greeting="welcomeMessage" :userData="currentUser" />
</template>

<script>
import ProfileCard from '@/components/ProfileCard.vue';

export default {
  data() {
    return {
      welcomeMessage: 'Hello World',
      currentUser: { name: 'Alice', role: 'Admin' }
    };
  },
  components: { ProfileCard }
}
</script>

Child Component (ProfileCard.vue):

<template>
  <div>{{ greeting }} - {{ userData.name }}</div>
</template>

<script>
export default {
  props: {
    greeting: { type: String, required: true },
    userData: { type: Object, required: true }
  }
}
</script>

Child to Parent: Data flows upward via custom events using $emit.

Child Component:

<template>
  <button @click="incrementCounter">Increment</button>
</template>

<script>
export default {
  data() {
    return { counter: 0 };
  },
  methods: {
    incrementCounter() {
      this.counter += 1;
      this.$emit('countUpdated', this.counter);
    }
  }
}
</script>

Parent Component:

<template>
  <div>
    <span>Latest: {{ latestCount }}</span>
    <ProfileCard @countUpdated="handleCountChange" />
  </div>
</template>

<script>
import ProfileCard from '@/components/ProfileCard.vue';

export default {
  data() {
    return { latestCount: 0 };
  },
  components: { ProfileCard },
  methods: {
    handleCountChange(newValue) {
      this.latestCount = newValue;
    }
  }
}
</script>

Sibling Communication: For non-hierarchical components, an EventBus facilitates communication.

  1. Create an event hub (eventHub.js):
import Vue from 'vue';
export default new Vue();
  1. Sender dispatches events via $emit:
<template>
  <button @click="broadcastData">Send Data</button>
</template>

<script>
import hub from './eventHub.js';

export default {
  data() {
    return { payload: 'Data from sibling' };
  },
  methods: {
    broadcastData() {
      hub.$emit('dataTransmitted', this.payload);
    }
  }
}
</script>
  1. Receiver listens via $on (typically inside the created hook):
<template>
  <div>{{ receivedData }}</div>
</template>

<script>
import hub from './eventHub.js';

export default {
  data() {
    return { receivedData: '' };
  },
  created() {
    hub.$on('dataTransmitted', (val) => {
      this.receivedData = val;
    });
  }
}
</script>
Tags: vue2

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.