Linn Linn Htun
Linn Linn Htun
AvatarLinn Linn Htun

Advanced Vue Components

August 17, 2023

Advanced Vue Components

Advanced Vue component patterns enable you to build more reusable, flexible, and maintainable applications. This post dives into advanced component techniques including scoped slots, the provide/inject pattern, dynamic and async components, composables for logic reuse, and best practices for structuring complex Vue component hierarchies.

Scaffolding a Vue Project

npm init vue@latest

npm install

npm run dev

 

How to pass props to child components?

Let's say we have User component and App. App component is parent component and User component is child component. Let's pass props from App to User like below:

in App.vue

<user :age="10" />

We're going to add a new property to the exported object called props in User.vue. 

in User.vue

export default {

props: ["age"]

}

props is short for properties. This will be set to an array, the array should contain a list of properties that the component will accept. It's important that the name inside the props array matches the attribute name. 

We can use props by using expression in template like this : 

{{ age }}

 

How to update props from the child component?

props not allowed to be updated in child components. This introduces bugs and unexpected behavior in our application. But what if we need to update a prop from a child component? We're going to be doing something called emitting events, the word emit means to produce or trigger something. When you click on a button or element, javascript will emit a click event. It doesn't call any specific functions. Instead, any code that listens for that event will run. 

In App.vue

<user @age-change="age++"></user>

in User.vue

<template>
<button type="button" @click="onClickAge"> Update Age </button>
</template>

<script>
export default{
methods: {
onClickAge() {
this.$emit('age-change');
}
}
}
</script>

 

we can add validation for props:

props: {
age : {
type: Number,
required: true,
default: 20,
validator(value) {
this.value < 130
}
}
},

 

Inserting content with slots

Slots are very popular among library developers. They can be really useful when you need to make your code more reusable.

in Form.vue

<template>
<form>
<slot></slot>
</form>
</template>

In App.vue

<template>
<app-form>
<input type="text">
</app-form>
</template>

<script>
import AppForm from "./components/Form.vue"

export default {
name: "App",
components: {
AppForm,
}
};
</script>

v-slot directive can be used to tell the child component where these slot content should be placed. We need to add a colon after this directive followed by the name. The name corresponds to the value we use for the name attribute in the child component.

in App.vue

<template>
<app-form>
<template v-slot:help>
<p>{{ help }}</p>
</template>
<template v-slot:fields>
<input type="text" placeholder="email">
<input type="text" placeholder="username">
<input type="password" placeholder="password">
</template>
<template v-slot:buttons>
<button type="submit">Submit</button>
</template>
<p>Dummy text</p>
</app-form>
<app-form>
<template v-slot:help>
<p>Contact help text.</p>
</template>
<template v-slot:fields>
<input type="text" placeholder="name">
<input type="text" placeholder="message">
</template>
<template v-slot:buttons>
<button type="submit">Submit</button>
</template>
</app-form>
</template>

<script>
import AppForm from "./components/Form.vue"

export default {
name: "App",
components: {
AppForm,
},
data() {
return {
help: 'This is some help text.'
}
}
};
</script>

in Form.vue

<template>
<form>
<div class="help">
<slot name="help"></slot>
</div>
<div class="fields">
<slot name="fields"></slot>
</div>
<div class="buttons">
<slot name="buttons"></slot>
</div>
<slot></slot>
</form>
</template>

 

 

Frequently Asked Questions

What are Vue slots and when should you use them?

Vue slots allow parent components to inject content into specific places in a child component's template, making components more flexible and reusable; scoped slots go further by passing data from the child back to the parent's slot content.

What is the difference between props and provide/inject in Vue?

Props pass data directly from parent to immediate child component; provide/inject allows an ancestor component to provide data that any descendant (no matter how deep) can inject, avoiding prop drilling in deeply nested component trees.