Class 5: Props & Slots
- Review: Last Class
- Props
- Slots
- Component Styling
Review: Last Class
Review: Event Handling
The v-on directive listens for DOM events and runs JavaScript code when they're triggered.
<script setup>
import { ref } from 'vue'
const count = ref(0)
function incrementCount() {
count.value++
}
</script>
<template>
<button v-on:click="incrementCount">
{{ count }}
</button>
</template>
Review: Event Handlers
In response to a DOM event, Vue.js can run a snippet of JavaScript code or call a function handler.
Inline Code
v-on:click="count++"
Review: Conditional Rendering
The v-if, v-else-if, v-else, and v-show directives conditionally render elements based on JavaScript expressions.
<script setup>
import { ref } from 'vue'
const isVisible = ref(true)
</script>
<template>
<div v-if="isVisible">
This element is visible.
</div>
</template>
Homework 2: Parts III, IV, && V
Discussion: Homework 2 - Parts I && II
- Part III: Props
- Part IV: Slots
- Part V: Styled Prototype
Props
Props
Custom attributes that allow JavaScript data to be passed from a parent component to a child component.
Defining Props
ChildComponent.vue:
<script setup>
defineProps(['propName1', 'propName2', ...])
</script>
Passing Props
<script setup>
import ChildComponent
from './components/ChildComponent.vue'
</script>
<template>
<ChildComponent
propName1="sample string 1"
propName2="sample string 2" />
</template>
Example: Props
Book.vue:
<script setup>
defineProps(['title', 'author'])
</script>
<template>
<hgroup>
<h2>{{ title }}</h2>
<p>by {{ author }}</p>
</hgroup>
</template>
App.vue:
<script setup>
import Book from './components/Book.vue'
</script>
<template>
<Book
title="The Great Gatsby"
author="F. Scott Fitzgerald" />
<Book
title="1984"
author="George Orwell" />
</template>
Gotcha: Props are Read-Only
Data flows from parent to child only.
Child components cannot modify prop values.
Gotcha: Default Value is a String
<ChildComponent propName="42" />
propName will be a string with the value "42", not a number with the value 42.
To pass other data types, we'll need to bind the prop using v-bind or the : shorthand. (Future class)
Slots
Slots
Placeholders inside a child component that allow HTML content to be passed from a parent component to a child component.
Passing Slot Content
<script setup>
import ChildComponent
from './components/ChildComponent.vue'
</script>
<template>
<ChildComponent>
<p>This is slot content.</p>
</ChildComponent>
</template>
Example: Slots
AlertBox.vue:
<template>
<div class="alert-box">
<slot></slot>
</div>
</template>
App.vue:
<script setup>
import AlertBox
from './components/AlertBox.vue'
</script>
<template>
<AlertBox>
<h2>Warning!</h2>
<p>This action cannot be undone.</p>
</AlertBox>
</template>
Named Slots
ChildComponent.vue:
<template>
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
</template>
App.vue:
<ChildComponent>
<template v-slot:header>
<h2>This is the header slot content.</h2>
</template>
<p>This is the default slot content.</p>
<template v-slot:footer>
<p>This is the footer slot content.</p>
</template>
</ChildComponent>
Shorthand: v-slot
# can be used as a shorthand for v-slot:
<ChildComponent>
<template #header>
<h2>This is the header slot content.</h2>
</template>
<p>This is the default slot content.</p>
<template #footer>
<p>This is the footer slot content.</p>
</template>
</ChildComponent>
<ChildComponent>
<template v-slot:header>
<h2>This is the header slot content.</h2>
</template>
<p>This is the default slot content.</p>
<template v-slot:footer>
<p>This is the footer slot content.</p>
</template>
</ChildComponent>
Activity: Props & Slots Practice
Working with your peers (2-4), correct the mistakes in the provided Menu.vue and App.vue components to implement a working hamburger menu using props and slots.
Vue.js Styling
Styling in Vue.js
Standard HTML elements can be styled.
<template>
<h1 class="title">
Hello, World!
</h1>
</template>
<style scoped>
.title {
color: blue;
}
</style>
Scoped Styles
By default, styles defined in a Vue component are scoped to that component only.
<style scoped>
.title {
color: blue;
}
</style>
This prevents styles from leaking out to other components or the global scope.
Gotcha: Unscoped Styles
If the scoped attribute is omitted, styles will apply globally to all components.
<style>
.title {
color: blue;
}
</style>
Any element with the title class in any component will be blue.
Global Styles
Global styles can be defined in the src/assets folder and imported in main.js:
import './assets/main.css'
/.assets/base.css- Base styles for the entire app/.assets/main.css- Main styles for the entire app
Gotcha: Vue.js Component's Cannot Use the Element Selector
<template>
<h1>Hello</h1>
<ChildComponent />
</template>
Only proper HTML elements can use the element selector: h1 { ... }
Vue.js components are not proper HTML elements and cannot use the element selector: ChildComponent { ... }
Studio: Homework 2
Working with your peers (2-4), complete Parts III, IV, and V of Homework 2.
Summary
- Props allow data to be passed from parent to child components.
- Slots allow HTML content to be passed from parent to child components.
- Styles can be scoped to individual components or applied globally.