(Go: >> BACK << -|- >> HOME <<)

SlideShare a Scribd company logo
VUE.JS SLOTS
Non farti sommergere dalle richieste di
personalizzazione!
COMMIT UNIVERSITY
Firenze, 19 Ottobre 2023
1
WHO AM I
Denny Biasiolli
Full Stack Developer
(JavaScript, Python, Go)
Front End Developer UX/ UI
Fingerprint Compliance Services Ltd.
Italy, Savigliano (CN)
@dennybiasiolli
denny.biasiolli@gmail.com
www.dennybiasiolli.com
2
Are you a lazy person?
3
Are you a lazy person?
(the really lazy ones wouldn't have raised their hand)
3.1
Bill Gates
I choose a lazy person to do a hard job.
Because a lazy person
will find an easy way to do it.
4
CUSTOMER'S FIRST REQUEST
Can you write a function that removes
all undefined values from an input
array?
5
FUNCTION SIGNATURE
export function removeUndefined<T>(array: T[]): T[] {
// ...
}
6
TDD APPROACH
import { it, expect } from 'vitest'
import { removeUndefined } from '../filtersV1'
it('removeUndefined removes `undefined` values', () => {
expect(
removeUndefined(['foo', undefined, 'bar'])
).toEqual(
['foo', 'bar']
)
})
7
IMPLEMENTATION
8
9
CUSTOMER'S CHANGE REQUEST
The function does not remove
null values!
10
FUNCTION SIGNATURE
(breaking change!)
// export function removeUndefined<T>(array: T[]): T[] {
export function customFilter<T>(
array: T[],
removeUndefined: boolean = true,
removeNull: boolean = false
): T[] {
// ...
}
11
IMPLEMENTATION
12
CUSTOMER'S CHANGE REQUEST
The function does not remove
empty values!
13
FUNCTION SIGNATURE
export function customFilter<T>(
array: T[],
removeUndefined: boolean = true,
removeNull: boolean = false,
+ removeEmpty: boolean = false
): T[] {
// ...
}
14
CUSTOMER'S CHANGE REQUESTS
The function does not remove
false values!
...zero values!
...zero as string values!
15
FUNCTION SIGNATURE
export function customFilter<T>(
array: T[],
removeUndefined: boolean = true,
removeNull: boolean = false,
removeEmpty: boolean = false,
+ removeFalse: boolean = false,
+ removeZero: boolean = false,
+ removeZeroString: boolean = false
): T[] {
// ...
}
16
IMPLEMENTATION
17
18
A smarter choice
19
IMPLEMENTATION
export function customFilter<T>(
array: T[],
filterFn: (element: T, index: number, array: T[]) => boolean
): T[] {
const retVal: T[] = []
for (let i = 0; i < array.length; i++) {
if (filterFn(array[i], i, array)) {
retVal.push(array[i])
}
}
return retVal
}
20
TESTS
it('should call the filterFn for each array element', () => {
const mockedFn = vi.fn().mockReturnValue(true)
const baseArray = ['foo', 'bar']
customFilter(baseArray, mockedFn)
expect(mockedFn).toHaveBeenCalledTimes(2);
for (let i = 0; i < baseArray.length; i++) {
expect(mockedFn).toHaveBeenNthCalledWith(
i + 1, baseArray[i], i, baseArray)
}
})
it('should filter when filterFn return value is truthy', () =>
const mockedFn = vi.fn()
.mockReturnValueOnce(true)
.mockReturnValueOnce(false)
.mockReturnValueOnce("123")
const retVal = customFilter(['foo', 'bar', 123], mockedFn)
expect(retVal).toEqual(['foo', 123])
})
21
USAGE
const myArray = ['foo', undefined, 'bar', null, false, '', 0,
customFilter(myArray, (elem) => (
elem !== undefined &&
elem !== null &&
elem !== false &&
elem !== '' &&
elem !== 0 &&
elem !== '0' &&
elem !== whateverValueIWantToExclude
))
22
FYI
Array.prototype.filter()
23
COMPONENTS PERSPECTIVE
Create a message box component
24
IMPLEMENTATION
export interface Props {
title?: string
message?: string
}
defineProps<Props>()
25
IMPLEMENTATION
<div class="message-box-title">
{{ title }}
</div>
<div class="message-box-message">
{{ message }}
</div>
26
POSSIBLE REQUESTS
custom title/message style
close button
footer section with
ok button
accept button
ok/cancel buttons
yes/no buttons
27
PSEUDO-IMPLEMENTATION
<div class="message-box-title">
{{ title || yourCustomTitleComponent }}
</div>
<div class="message-box-message">
{{ message || yourCustomMessageComponent }}
</div>
{{ yourCustomFooterComponent }}
28
29
WHAT ARE SLOTS IN VUE.JS?
A way to pass content to a component
30
USAGE OF SLOTS IN VUE.JS
1. define a section of a component’s template that can
be replaced by the parent component
2. the parent component controls the layout and
content of the child component
31
SLOT CONTENT AND OUTLET
1. allow a component to accept dynamic content
2. pass a template fragment to a child component
<button class="fancy-btn">
<slot></slot> <!-- slot outlet -->
</button>
<FancyButton>
Click me! <!-- slot content -->
</FancyButton>
32
SLOT CONTENT AND OUTLET
<button class="fancy-btn">Click me!</button>
33
SLOT CONTENT AND OUTLET
FancyButton is responsible for rendering the
outer <button> and its styling
the inner content (and its style) is provided by the
parent component
34
SLOT CONTENT AND OUTLET
Slot content is not just limited to text!
<FancyButton>
<span style="color:red">Click me!</span>
<AwesomeIcon name="plus" />
</FancyButton>
35
SLOT CONTENT AND OUTLET
<FancyButton> is flexible and reusable.
We can now use it in different places with different
inner content, but all with the same fancy styling.
36
RENDER SCOPE
Slot content
has access to the data scope of the parent
component
does not have access to the child component's data
<span>{{ message }}</span>
<FancyButton>{{ message }}</FancyButton>
37
FALLBACK CONTENT
Default value for a slot content
Rendered only when no content is provided
<button type="submit">
<slot>
Submit <!-- fallback content -->
</slot>
</button>
38
FALLBACK CONTENT
Examples
<SubmitButton />
<!-- rendered as -->
<button type="submit">Submit</button>
<SubmitButton>Save</SubmitButton>
<!-- rendered as -->
<button type="submit">Save</button>
39
NAMED SLOTS
Multiple slot outlets in the same component.
<div class="container">
<header>
<!-- We want header content here -->
</header>
<main>
<!-- We want main content here -->
</main>
<footer>
<!-- We want footer content here -->
</footer>
</div>
40
NAMED SLOTS
<slot> attribute name
<slot> without name
implicitly has the name "default".
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
41
PASSING NAMED SLOTS
<template> element with the v-slot directive
"#" can replace v-slot
<template v-slot:header>
<!-- content for the header slot -->
</template>
<template #header>
<!-- content for the header slot -->
</template>
42
PASSING NAMED SLOTS
43
PASSING NAMED SLOTS
<template #default> can be omitted
<BaseLayout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<template #default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template #footer>
<p>Here's some contact info</p>
</template>
</BaseLayout>
44
PASSING NAMED SLOTS
is the same as
<BaseLayout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<!-- implicit default slot -->
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #footer>
<p>Here's some contact info</p>
</template>
</BaseLayout>
45
SCOPED SLOTS
Yes, but...
The parent component does not have
access to the child component's data
We can pass attributes to a slot outlet
46
SCOPED SLOTS
Passing attributes to a slot outlet
Receiving slot props in the template
<slot :text="greetingMessage" :count="1"></slot>
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
<!-- or -->
<MyComponent v-slot="{ text, count}">
{{ text }} {{ count }}
</MyComponent>
47
SCOPED SLOTS
48
SCOPED SLOTS
is the same as
<MyComponent v-slot="{ text, count}">
{{ text }} {{ count }}
</MyComponent>
<MyComponent>
<template #default="{ text, count}">
{{ text }} {{ count }}
</template>
</MyComponent>
49
NAMED SCOPED SLOTS
"name" is reserved, the scope will be
<slot name="header" message="hello"></slot>
{ message: 'hello' }
50
NAMED SCOPED SLOTS
<MyComponent>
<template #header="headerProps">
{{ headerProps }}
</template>
<template #default="defaultProps">
{{ defaultProps }}
</template>
<template #footer="footerProps">
{{ footerProps }}
</template>
</MyComponent>
51
NAMED SCOPED SLOTS
Where is the error?
<template>
<MyComponent v-slot="{ message }">
<p>{{ message }}</p>
<template #footer>
<p>{{ message }}</p>
</template>
</MyComponent>
</template>
52
NAMED SCOPED SLOTS
Where is the error?
<template>
<MyComponent>
<template #default="{ message }">
<p>{{ message }}</p>
</template>
<template #footer>
<!-- message belongs to the default slot
it is not available here -->
<p>{{ message }}</p>
</template>
</MyComponent>
</template>
53
Wait a minute
54
CUSTOMER'S REQUEST
Write a component to display the
composition of a pizza,
with crust style/composition, sauce
and toppings.
55
PIZZA COMPONENT
defineProps([
"name",
"crustStyle",
"crustComposition",
"sauce",
"topping",
])
56
PIZZA TEMPLATE
<div class="pizza-box">
<h1 class="pizza-title">{{ name }}</h1>
<slot name="pizza">
<!-- all other slots -->
</slot>
</div>
57
PIZZA TEMPLATE
<slot name="crust">
<div>
{{ crustStyle.name }}, with {{ crustComposition.name }}
</div>
</slot>
<slot name="sauce">
<div>{{ sauce.name }}</div>
</slot>
<slot name="toppings">
Toppings:
<ul>
<li v-for="topping in toppings" :key="topping.key">
<slot name="topping" :topping="topping">
{{ topping.name }}
</slot>
</li>
</ul>
</slot>
58
DEMO!
59
TEST TIME!
60
HOW TO TEST SLOTS?
Using @vue/test-utils
test-utils.vuejs.org/guide/advanced/slots.html
61
TESTING SLOTS
test('default content', () => {
const wrapper = mount(MyComponent)
expect(wrapper.html()).toMatchSnapshot()
})
62
TESTING SLOTS
test('default slot', () => {
const wrapper = mount(MyComponent, {
slots: {
default: 'Main Content'
}
})
// expect(wrapper.html()).toMatchSnapshot()
expect(wrapper.html()).toContain('Main Content')
// expect(wrapper.find('main').text()).toContain('Main Conte
})
63
TESTING SLOTS
test('named slots', () => {
const wrapper = mount(MyComponent, {
slots: {
header: '<div>Header</div>',
main: '<div>Main Content</div>',
footer: '<div>Footer</div>'
}
})
expect(wrapper.html()).toContain('<div>Header</div>')
expect(wrapper.html()).toContain('<div>Main Content</div>')
expect(wrapper.html()).toContain('<div>Footer</div>')
})
64
TESTING SLOTS
import { h } from 'vue'
import Header from './Header.vue'
test('advanced usage', () => {
const wrapper = mount(MyComponent, {
slots: {
header: Header,
main: h('div', 'Main Content'),
sidebar: { template: '<div>Sidebar</div>' },
footer: '<div>Footer</div>'
}
})
})
65
TESTING SLOTS
test('scoped slots', () => {
const wrapper = mount(MyComponent, {
slots: {
footer: `<template #footer="scopeObj">
{{ scopeObj.msg }}
</template>`,
// or
footer: `<template #footer="{ msg }">
{{ msg }}
</template>`,
// or
footer: '{{ params.msg }}'
}
})
})
66
THANK YOU!
Talk inspired by: "IOC, (inversion of control)" by Omar De Angelis
@dennybiasiolli
vuejs.org/guide/components/slots.html
test-utils.vuejs.org/guide/advanced/slots.html
github.com/dennybiasiolli/vue-slots-examples
www.dennybiasiolli.com
67

More Related Content

Similar to Vue.js slots.pdf

Complete DB code following the instructions Implement the D.pdf
Complete DB code following the instructions Implement the D.pdfComplete DB code following the instructions Implement the D.pdf
Complete DB code following the instructions Implement the D.pdf
access2future1
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수
용 최
 
20.1 Java working with abstraction
20.1 Java working with abstraction20.1 Java working with abstraction
20.1 Java working with abstraction
Intro C# Book
 
Documentation For Tab Setup
Documentation For Tab SetupDocumentation For Tab Setup
Documentation For Tab Setup
vkeeton
 
Prompt engineering for iOS developers (How LLMs and GenAI work)
Prompt engineering for iOS developers (How LLMs and GenAI work)Prompt engineering for iOS developers (How LLMs and GenAI work)
Prompt engineering for iOS developers (How LLMs and GenAI work)
Andrey Volobuev
 
JavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScriptJavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScript
Laurence Svekis ✔
 
python modules1522.pdf
python modules1522.pdfpython modules1522.pdf
python modules1522.pdf
DebanjanMaity13
 
Computer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperComputer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paper
Deepak Singh
 
Mocks Enabling Test-Driven Design
Mocks Enabling Test-Driven DesignMocks Enabling Test-Driven Design
Mocks Enabling Test-Driven Design
Alexandre Martins
 
Quest 1 define a class batsman with the following specifications
Quest  1 define a class batsman with the following specificationsQuest  1 define a class batsman with the following specifications
Quest 1 define a class batsman with the following specifications
rajkumari873
 
C++ Nested loops, matrix and fuctions.pdf
C++ Nested loops, matrix and fuctions.pdfC++ Nested loops, matrix and fuctions.pdf
C++ Nested loops, matrix and fuctions.pdf
yamew16788
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
Han Lee
 
Postgres can do THAT?
Postgres can do THAT?Postgres can do THAT?
Postgres can do THAT?
alexbrasetvik
 
Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
Bernhard Schussek
 
Managing console
Managing consoleManaging console
Managing console
Shiva Saxena
 
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
takeoutweight
 
Visual Basic 6.0
Visual Basic 6.0Visual Basic 6.0
Visual Basic 6.0
Palitha Baddegama
 
Rhino Mocks
Rhino MocksRhino Mocks
Rhino Mocks
Anand Kumar Rajana
 
C++ practical
C++ practicalC++ practical
C++ practical
Rahul juneja
 
C-Sharp Arithmatic Expression Calculator
C-Sharp Arithmatic Expression CalculatorC-Sharp Arithmatic Expression Calculator
C-Sharp Arithmatic Expression Calculator
Neeraj Kaushik
 

Similar to Vue.js slots.pdf (20)

Complete DB code following the instructions Implement the D.pdf
Complete DB code following the instructions Implement the D.pdfComplete DB code following the instructions Implement the D.pdf
Complete DB code following the instructions Implement the D.pdf
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수
 
20.1 Java working with abstraction
20.1 Java working with abstraction20.1 Java working with abstraction
20.1 Java working with abstraction
 
Documentation For Tab Setup
Documentation For Tab SetupDocumentation For Tab Setup
Documentation For Tab Setup
 
Prompt engineering for iOS developers (How LLMs and GenAI work)
Prompt engineering for iOS developers (How LLMs and GenAI work)Prompt engineering for iOS developers (How LLMs and GenAI work)
Prompt engineering for iOS developers (How LLMs and GenAI work)
 
JavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScriptJavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScript
 
python modules1522.pdf
python modules1522.pdfpython modules1522.pdf
python modules1522.pdf
 
Computer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperComputer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paper
 
Mocks Enabling Test-Driven Design
Mocks Enabling Test-Driven DesignMocks Enabling Test-Driven Design
Mocks Enabling Test-Driven Design
 
Quest 1 define a class batsman with the following specifications
Quest  1 define a class batsman with the following specificationsQuest  1 define a class batsman with the following specifications
Quest 1 define a class batsman with the following specifications
 
C++ Nested loops, matrix and fuctions.pdf
C++ Nested loops, matrix and fuctions.pdfC++ Nested loops, matrix and fuctions.pdf
C++ Nested loops, matrix and fuctions.pdf
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
 
Postgres can do THAT?
Postgres can do THAT?Postgres can do THAT?
Postgres can do THAT?
 
Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
 
Managing console
Managing consoleManaging console
Managing console
 
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
 
Visual Basic 6.0
Visual Basic 6.0Visual Basic 6.0
Visual Basic 6.0
 
Rhino Mocks
Rhino MocksRhino Mocks
Rhino Mocks
 
C++ practical
C++ practicalC++ practical
C++ practical
 
C-Sharp Arithmatic Expression Calculator
C-Sharp Arithmatic Expression CalculatorC-Sharp Arithmatic Expression Calculator
C-Sharp Arithmatic Expression Calculator
 

More from Commit University

Oltre l'hype: vulnerabilità e limiti dell'intelligenza artificiale.pdf
Oltre l'hype: vulnerabilità e limiti dell'intelligenza artificiale.pdfOltre l'hype: vulnerabilità e limiti dell'intelligenza artificiale.pdf
Oltre l'hype: vulnerabilità e limiti dell'intelligenza artificiale.pdf
Commit University
 
Alla scoperta dei Vector Database e dei RAG
Alla scoperta dei Vector Database e dei RAGAlla scoperta dei Vector Database e dei RAG
Alla scoperta dei Vector Database e dei RAG
Commit University
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
Commit University
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Commit University
 
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfBreaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Commit University
 
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdfAccelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Commit University
 
Slide-10years.pdf
Slide-10years.pdfSlide-10years.pdf
Slide-10years.pdf
Commit University
 
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Commit University
 
Commit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptx
Commit University
 
Sviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PASviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PA
Commit University
 
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Commit University
 
Prisma the ORM that node was waiting for
Prisma the ORM that node was waiting forPrisma the ORM that node was waiting for
Prisma the ORM that node was waiting for
Commit University
 
Decision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityDecision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit University
Commit University
 
Component Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfComponent Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdf
Commit University
 
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Commit University
 
Prototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsPrototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step Functions
Commit University
 
KMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftKMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and Swift
Commit University
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazione
Commit University
 
Orchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcOrchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lc
Commit University
 
Fastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeFastify has defeated Lagacy-Code
Fastify has defeated Lagacy-Code
Commit University
 

More from Commit University (20)

Oltre l'hype: vulnerabilità e limiti dell'intelligenza artificiale.pdf
Oltre l'hype: vulnerabilità e limiti dell'intelligenza artificiale.pdfOltre l'hype: vulnerabilità e limiti dell'intelligenza artificiale.pdf
Oltre l'hype: vulnerabilità e limiti dell'intelligenza artificiale.pdf
 
Alla scoperta dei Vector Database e dei RAG
Alla scoperta dei Vector Database e dei RAGAlla scoperta dei Vector Database e dei RAG
Alla scoperta dei Vector Database e dei RAG
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfBreaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
 
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdfAccelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
 
Slide-10years.pdf
Slide-10years.pdfSlide-10years.pdf
Slide-10years.pdf
 
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
 
Commit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptx
 
Sviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PASviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PA
 
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
 
Prisma the ORM that node was waiting for
Prisma the ORM that node was waiting forPrisma the ORM that node was waiting for
Prisma the ORM that node was waiting for
 
Decision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityDecision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit University
 
Component Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfComponent Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdf
 
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
 
Prototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsPrototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step Functions
 
KMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftKMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and Swift
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazione
 
Orchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcOrchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lc
 
Fastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeFastify has defeated Lagacy-Code
Fastify has defeated Lagacy-Code
 

Recently uploaded

INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdfINDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
jackson110191
 
Interaction Latency: Square's User-Centric Mobile Performance Metric
Interaction Latency: Square's User-Centric Mobile Performance MetricInteraction Latency: Square's User-Centric Mobile Performance Metric
Interaction Latency: Square's User-Centric Mobile Performance Metric
ScyllaDB
 
STKI Israeli Market Study 2024 final v1
STKI Israeli Market Study 2024 final  v1STKI Israeli Market Study 2024 final  v1
STKI Israeli Market Study 2024 final v1
Dr. Jimmy Schwarzkopf
 
Running a Go App in Kubernetes: CPU Impacts
Running a Go App in Kubernetes: CPU ImpactsRunning a Go App in Kubernetes: CPU Impacts
Running a Go App in Kubernetes: CPU Impacts
ScyllaDB
 
Implementations of Fused Deposition Modeling in real world
Implementations of Fused Deposition Modeling  in real worldImplementations of Fused Deposition Modeling  in real world
Implementations of Fused Deposition Modeling in real world
Emerging Tech
 
What’s New in Teams Calling, Meetings and Devices May 2024
What’s New in Teams Calling, Meetings and Devices May 2024What’s New in Teams Calling, Meetings and Devices May 2024
What’s New in Teams Calling, Meetings and Devices May 2024
Stephanie Beckett
 
UiPath Community Day Kraków: Devs4Devs Conference
UiPath Community Day Kraków: Devs4Devs ConferenceUiPath Community Day Kraków: Devs4Devs Conference
UiPath Community Day Kraków: Devs4Devs Conference
UiPathCommunity
 
HTTP Adaptive Streaming – Quo Vadis (2024)
HTTP Adaptive Streaming – Quo Vadis (2024)HTTP Adaptive Streaming – Quo Vadis (2024)
HTTP Adaptive Streaming – Quo Vadis (2024)
Alpen-Adria-Universität
 
5G bootcamp Sep 2020 (NPI initiative).pptx
5G bootcamp Sep 2020 (NPI initiative).pptx5G bootcamp Sep 2020 (NPI initiative).pptx
5G bootcamp Sep 2020 (NPI initiative).pptx
SATYENDRA100
 
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Erasmo Purificato
 
How RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptxHow RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptx
SynapseIndia
 
What's Next Web Development Trends to Watch.pdf
What's Next Web Development Trends to Watch.pdfWhat's Next Web Development Trends to Watch.pdf
What's Next Web Development Trends to Watch.pdf
SeasiaInfotech2
 
The Rise of Supernetwork Data Intensive Computing
The Rise of Supernetwork Data Intensive ComputingThe Rise of Supernetwork Data Intensive Computing
The Rise of Supernetwork Data Intensive Computing
Larry Smarr
 
Data Protection in a Connected World: Sovereignty and Cyber Security
Data Protection in a Connected World: Sovereignty and Cyber SecurityData Protection in a Connected World: Sovereignty and Cyber Security
Data Protection in a Connected World: Sovereignty and Cyber Security
anupriti
 
Observability For You and Me with OpenTelemetry
Observability For You and Me with OpenTelemetryObservability For You and Me with OpenTelemetry
Observability For You and Me with OpenTelemetry
Eric D. Schabell
 
Cookies program to display the information though cookie creation
Cookies program to display the information though cookie creationCookies program to display the information though cookie creation
Cookies program to display the information though cookie creation
shanthidl1
 
Research Directions for Cross Reality Interfaces
Research Directions for Cross Reality InterfacesResearch Directions for Cross Reality Interfaces
Research Directions for Cross Reality Interfaces
Mark Billinghurst
 
Navigating Post-Quantum Blockchain: Resilient Cryptography in Quantum Threats
Navigating Post-Quantum Blockchain: Resilient Cryptography in Quantum ThreatsNavigating Post-Quantum Blockchain: Resilient Cryptography in Quantum Threats
Navigating Post-Quantum Blockchain: Resilient Cryptography in Quantum Threats
anupriti
 
What Not to Document and Why_ (North Bay Python 2024)
What Not to Document and Why_ (North Bay Python 2024)What Not to Document and Why_ (North Bay Python 2024)
What Not to Document and Why_ (North Bay Python 2024)
Margaret Fero
 
this resume for sadika shaikh bca student
this resume for sadika shaikh bca studentthis resume for sadika shaikh bca student
this resume for sadika shaikh bca student
SadikaShaikh7
 

Recently uploaded (20)

INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdfINDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
 
Interaction Latency: Square's User-Centric Mobile Performance Metric
Interaction Latency: Square's User-Centric Mobile Performance MetricInteraction Latency: Square's User-Centric Mobile Performance Metric
Interaction Latency: Square's User-Centric Mobile Performance Metric
 
STKI Israeli Market Study 2024 final v1
STKI Israeli Market Study 2024 final  v1STKI Israeli Market Study 2024 final  v1
STKI Israeli Market Study 2024 final v1
 
Running a Go App in Kubernetes: CPU Impacts
Running a Go App in Kubernetes: CPU ImpactsRunning a Go App in Kubernetes: CPU Impacts
Running a Go App in Kubernetes: CPU Impacts
 
Implementations of Fused Deposition Modeling in real world
Implementations of Fused Deposition Modeling  in real worldImplementations of Fused Deposition Modeling  in real world
Implementations of Fused Deposition Modeling in real world
 
What’s New in Teams Calling, Meetings and Devices May 2024
What’s New in Teams Calling, Meetings and Devices May 2024What’s New in Teams Calling, Meetings and Devices May 2024
What’s New in Teams Calling, Meetings and Devices May 2024
 
UiPath Community Day Kraków: Devs4Devs Conference
UiPath Community Day Kraków: Devs4Devs ConferenceUiPath Community Day Kraków: Devs4Devs Conference
UiPath Community Day Kraków: Devs4Devs Conference
 
HTTP Adaptive Streaming – Quo Vadis (2024)
HTTP Adaptive Streaming – Quo Vadis (2024)HTTP Adaptive Streaming – Quo Vadis (2024)
HTTP Adaptive Streaming – Quo Vadis (2024)
 
5G bootcamp Sep 2020 (NPI initiative).pptx
5G bootcamp Sep 2020 (NPI initiative).pptx5G bootcamp Sep 2020 (NPI initiative).pptx
5G bootcamp Sep 2020 (NPI initiative).pptx
 
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
 
How RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptxHow RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptx
 
What's Next Web Development Trends to Watch.pdf
What's Next Web Development Trends to Watch.pdfWhat's Next Web Development Trends to Watch.pdf
What's Next Web Development Trends to Watch.pdf
 
The Rise of Supernetwork Data Intensive Computing
The Rise of Supernetwork Data Intensive ComputingThe Rise of Supernetwork Data Intensive Computing
The Rise of Supernetwork Data Intensive Computing
 
Data Protection in a Connected World: Sovereignty and Cyber Security
Data Protection in a Connected World: Sovereignty and Cyber SecurityData Protection in a Connected World: Sovereignty and Cyber Security
Data Protection in a Connected World: Sovereignty and Cyber Security
 
Observability For You and Me with OpenTelemetry
Observability For You and Me with OpenTelemetryObservability For You and Me with OpenTelemetry
Observability For You and Me with OpenTelemetry
 
Cookies program to display the information though cookie creation
Cookies program to display the information though cookie creationCookies program to display the information though cookie creation
Cookies program to display the information though cookie creation
 
Research Directions for Cross Reality Interfaces
Research Directions for Cross Reality InterfacesResearch Directions for Cross Reality Interfaces
Research Directions for Cross Reality Interfaces
 
Navigating Post-Quantum Blockchain: Resilient Cryptography in Quantum Threats
Navigating Post-Quantum Blockchain: Resilient Cryptography in Quantum ThreatsNavigating Post-Quantum Blockchain: Resilient Cryptography in Quantum Threats
Navigating Post-Quantum Blockchain: Resilient Cryptography in Quantum Threats
 
What Not to Document and Why_ (North Bay Python 2024)
What Not to Document and Why_ (North Bay Python 2024)What Not to Document and Why_ (North Bay Python 2024)
What Not to Document and Why_ (North Bay Python 2024)
 
this resume for sadika shaikh bca student
this resume for sadika shaikh bca studentthis resume for sadika shaikh bca student
this resume for sadika shaikh bca student
 

Vue.js slots.pdf

  • 1. VUE.JS SLOTS Non farti sommergere dalle richieste di personalizzazione! COMMIT UNIVERSITY Firenze, 19 Ottobre 2023 1
  • 2. WHO AM I Denny Biasiolli Full Stack Developer (JavaScript, Python, Go) Front End Developer UX/ UI Fingerprint Compliance Services Ltd. Italy, Savigliano (CN) @dennybiasiolli denny.biasiolli@gmail.com www.dennybiasiolli.com 2
  • 3. Are you a lazy person? 3
  • 4. Are you a lazy person? (the really lazy ones wouldn't have raised their hand) 3.1
  • 5. Bill Gates I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it. 4
  • 6. CUSTOMER'S FIRST REQUEST Can you write a function that removes all undefined values from an input array? 5
  • 7. FUNCTION SIGNATURE export function removeUndefined<T>(array: T[]): T[] { // ... } 6
  • 8. TDD APPROACH import { it, expect } from 'vitest' import { removeUndefined } from '../filtersV1' it('removeUndefined removes `undefined` values', () => { expect( removeUndefined(['foo', undefined, 'bar']) ).toEqual( ['foo', 'bar'] ) }) 7
  • 10. 9
  • 11. CUSTOMER'S CHANGE REQUEST The function does not remove null values! 10
  • 12. FUNCTION SIGNATURE (breaking change!) // export function removeUndefined<T>(array: T[]): T[] { export function customFilter<T>( array: T[], removeUndefined: boolean = true, removeNull: boolean = false ): T[] { // ... } 11
  • 14. CUSTOMER'S CHANGE REQUEST The function does not remove empty values! 13
  • 15. FUNCTION SIGNATURE export function customFilter<T>( array: T[], removeUndefined: boolean = true, removeNull: boolean = false, + removeEmpty: boolean = false ): T[] { // ... } 14
  • 16. CUSTOMER'S CHANGE REQUESTS The function does not remove false values! ...zero values! ...zero as string values! 15
  • 17. FUNCTION SIGNATURE export function customFilter<T>( array: T[], removeUndefined: boolean = true, removeNull: boolean = false, removeEmpty: boolean = false, + removeFalse: boolean = false, + removeZero: boolean = false, + removeZeroString: boolean = false ): T[] { // ... } 16
  • 19. 18
  • 21. IMPLEMENTATION export function customFilter<T>( array: T[], filterFn: (element: T, index: number, array: T[]) => boolean ): T[] { const retVal: T[] = [] for (let i = 0; i < array.length; i++) { if (filterFn(array[i], i, array)) { retVal.push(array[i]) } } return retVal } 20
  • 22. TESTS it('should call the filterFn for each array element', () => { const mockedFn = vi.fn().mockReturnValue(true) const baseArray = ['foo', 'bar'] customFilter(baseArray, mockedFn) expect(mockedFn).toHaveBeenCalledTimes(2); for (let i = 0; i < baseArray.length; i++) { expect(mockedFn).toHaveBeenNthCalledWith( i + 1, baseArray[i], i, baseArray) } }) it('should filter when filterFn return value is truthy', () => const mockedFn = vi.fn() .mockReturnValueOnce(true) .mockReturnValueOnce(false) .mockReturnValueOnce("123") const retVal = customFilter(['foo', 'bar', 123], mockedFn) expect(retVal).toEqual(['foo', 123]) }) 21
  • 23. USAGE const myArray = ['foo', undefined, 'bar', null, false, '', 0, customFilter(myArray, (elem) => ( elem !== undefined && elem !== null && elem !== false && elem !== '' && elem !== 0 && elem !== '0' && elem !== whateverValueIWantToExclude )) 22
  • 25. COMPONENTS PERSPECTIVE Create a message box component 24
  • 26. IMPLEMENTATION export interface Props { title?: string message?: string } defineProps<Props>() 25
  • 27. IMPLEMENTATION <div class="message-box-title"> {{ title }} </div> <div class="message-box-message"> {{ message }} </div> 26
  • 28. POSSIBLE REQUESTS custom title/message style close button footer section with ok button accept button ok/cancel buttons yes/no buttons 27
  • 29. PSEUDO-IMPLEMENTATION <div class="message-box-title"> {{ title || yourCustomTitleComponent }} </div> <div class="message-box-message"> {{ message || yourCustomMessageComponent }} </div> {{ yourCustomFooterComponent }} 28
  • 30. 29
  • 31. WHAT ARE SLOTS IN VUE.JS? A way to pass content to a component 30
  • 32. USAGE OF SLOTS IN VUE.JS 1. define a section of a component’s template that can be replaced by the parent component 2. the parent component controls the layout and content of the child component 31
  • 33. SLOT CONTENT AND OUTLET 1. allow a component to accept dynamic content 2. pass a template fragment to a child component <button class="fancy-btn"> <slot></slot> <!-- slot outlet --> </button> <FancyButton> Click me! <!-- slot content --> </FancyButton> 32
  • 34. SLOT CONTENT AND OUTLET <button class="fancy-btn">Click me!</button> 33
  • 35. SLOT CONTENT AND OUTLET FancyButton is responsible for rendering the outer <button> and its styling the inner content (and its style) is provided by the parent component 34
  • 36. SLOT CONTENT AND OUTLET Slot content is not just limited to text! <FancyButton> <span style="color:red">Click me!</span> <AwesomeIcon name="plus" /> </FancyButton> 35
  • 37. SLOT CONTENT AND OUTLET <FancyButton> is flexible and reusable. We can now use it in different places with different inner content, but all with the same fancy styling. 36
  • 38. RENDER SCOPE Slot content has access to the data scope of the parent component does not have access to the child component's data <span>{{ message }}</span> <FancyButton>{{ message }}</FancyButton> 37
  • 39. FALLBACK CONTENT Default value for a slot content Rendered only when no content is provided <button type="submit"> <slot> Submit <!-- fallback content --> </slot> </button> 38
  • 40. FALLBACK CONTENT Examples <SubmitButton /> <!-- rendered as --> <button type="submit">Submit</button> <SubmitButton>Save</SubmitButton> <!-- rendered as --> <button type="submit">Save</button> 39
  • 41. NAMED SLOTS Multiple slot outlets in the same component. <div class="container"> <header> <!-- We want header content here --> </header> <main> <!-- We want main content here --> </main> <footer> <!-- We want footer content here --> </footer> </div> 40
  • 42. NAMED SLOTS <slot> attribute name <slot> without name implicitly has the name "default". <div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> 41
  • 43. PASSING NAMED SLOTS <template> element with the v-slot directive "#" can replace v-slot <template v-slot:header> <!-- content for the header slot --> </template> <template #header> <!-- content for the header slot --> </template> 42
  • 45. PASSING NAMED SLOTS <template #default> can be omitted <BaseLayout> <template #header> <h1>Here might be a page title</h1> </template> <template #default> <p>A paragraph for the main content.</p> <p>And another one.</p> </template> <template #footer> <p>Here's some contact info</p> </template> </BaseLayout> 44
  • 46. PASSING NAMED SLOTS is the same as <BaseLayout> <template #header> <h1>Here might be a page title</h1> </template> <!-- implicit default slot --> <p>A paragraph for the main content.</p> <p>And another one.</p> <template #footer> <p>Here's some contact info</p> </template> </BaseLayout> 45
  • 47. SCOPED SLOTS Yes, but... The parent component does not have access to the child component's data We can pass attributes to a slot outlet 46
  • 48. SCOPED SLOTS Passing attributes to a slot outlet Receiving slot props in the template <slot :text="greetingMessage" :count="1"></slot> <MyComponent v-slot="slotProps"> {{ slotProps.text }} {{ slotProps.count }} </MyComponent> <!-- or --> <MyComponent v-slot="{ text, count}"> {{ text }} {{ count }} </MyComponent> 47
  • 50. SCOPED SLOTS is the same as <MyComponent v-slot="{ text, count}"> {{ text }} {{ count }} </MyComponent> <MyComponent> <template #default="{ text, count}"> {{ text }} {{ count }} </template> </MyComponent> 49
  • 51. NAMED SCOPED SLOTS "name" is reserved, the scope will be <slot name="header" message="hello"></slot> { message: 'hello' } 50
  • 52. NAMED SCOPED SLOTS <MyComponent> <template #header="headerProps"> {{ headerProps }} </template> <template #default="defaultProps"> {{ defaultProps }} </template> <template #footer="footerProps"> {{ footerProps }} </template> </MyComponent> 51
  • 53. NAMED SCOPED SLOTS Where is the error? <template> <MyComponent v-slot="{ message }"> <p>{{ message }}</p> <template #footer> <p>{{ message }}</p> </template> </MyComponent> </template> 52
  • 54. NAMED SCOPED SLOTS Where is the error? <template> <MyComponent> <template #default="{ message }"> <p>{{ message }}</p> </template> <template #footer> <!-- message belongs to the default slot it is not available here --> <p>{{ message }}</p> </template> </MyComponent> </template> 53
  • 56. CUSTOMER'S REQUEST Write a component to display the composition of a pizza, with crust style/composition, sauce and toppings. 55
  • 58. PIZZA TEMPLATE <div class="pizza-box"> <h1 class="pizza-title">{{ name }}</h1> <slot name="pizza"> <!-- all other slots --> </slot> </div> 57
  • 59. PIZZA TEMPLATE <slot name="crust"> <div> {{ crustStyle.name }}, with {{ crustComposition.name }} </div> </slot> <slot name="sauce"> <div>{{ sauce.name }}</div> </slot> <slot name="toppings"> Toppings: <ul> <li v-for="topping in toppings" :key="topping.key"> <slot name="topping" :topping="topping"> {{ topping.name }} </slot> </li> </ul> </slot> 58
  • 62. HOW TO TEST SLOTS? Using @vue/test-utils test-utils.vuejs.org/guide/advanced/slots.html 61
  • 63. TESTING SLOTS test('default content', () => { const wrapper = mount(MyComponent) expect(wrapper.html()).toMatchSnapshot() }) 62
  • 64. TESTING SLOTS test('default slot', () => { const wrapper = mount(MyComponent, { slots: { default: 'Main Content' } }) // expect(wrapper.html()).toMatchSnapshot() expect(wrapper.html()).toContain('Main Content') // expect(wrapper.find('main').text()).toContain('Main Conte }) 63
  • 65. TESTING SLOTS test('named slots', () => { const wrapper = mount(MyComponent, { slots: { header: '<div>Header</div>', main: '<div>Main Content</div>', footer: '<div>Footer</div>' } }) expect(wrapper.html()).toContain('<div>Header</div>') expect(wrapper.html()).toContain('<div>Main Content</div>') expect(wrapper.html()).toContain('<div>Footer</div>') }) 64
  • 66. TESTING SLOTS import { h } from 'vue' import Header from './Header.vue' test('advanced usage', () => { const wrapper = mount(MyComponent, { slots: { header: Header, main: h('div', 'Main Content'), sidebar: { template: '<div>Sidebar</div>' }, footer: '<div>Footer</div>' } }) }) 65
  • 67. TESTING SLOTS test('scoped slots', () => { const wrapper = mount(MyComponent, { slots: { footer: `<template #footer="scopeObj"> {{ scopeObj.msg }} </template>`, // or footer: `<template #footer="{ msg }"> {{ msg }} </template>`, // or footer: '{{ params.msg }}' } }) }) 66
  • 68. THANK YOU! Talk inspired by: "IOC, (inversion of control)" by Omar De Angelis @dennybiasiolli vuejs.org/guide/components/slots.html test-utils.vuejs.org/guide/advanced/slots.html github.com/dennybiasiolli/vue-slots-examples www.dennybiasiolli.com 67