SlideShare a Scribd company logo
Vue.js Renderless Components
It’s like advanced internet Legos!
ToThePoint STS / Lars van Herk / 3 june, 2019
1. Build a standard, feature-rich base component
2. Separate the view from the logic
3. Slap it into a publishable library
WHAT’CHA GONNA DO?
INTRODUCTION
We’re gonna do some Vue.
WHY SO COMPLICATED?
INTRODUCTION
Every app works differently
- “Our date pickers don’t look like that!”
- Tweaking a prebuilt component’s layout is
hard or impossible
- Either accept it, or rebuild it
WHAT DO WE NEED FOR THIS?
INTRODUCTION
Slots. Scoped Slots.
https://vuejs.org/v2/guide/components-slots.html
<template>
<section class="my-alert">
<slot name="title">
<h1>This will be the default title!</h1>
</slot>
<slot v-bind:person="person">
Hello, {{ person.name }}!
</slot>
</section>
</template>
<template>
<div id="app">
<my-alert :person="outerPerson">
<template v-slot:title>
<h1>I'm going to replace the default!</h1>
</template>
</my-alert>
</div>
</template>
<template>
<section class="my-alert">
<h1>I'm going to replace the default!</h1>
Hello, Bobby!
</section>
</template>
MyAlert.vue
App.vue
Rendered Output
INTRODUCTION
RENDERING ALL THE THINGS!
INTRODUCTION
- Template part of SFC isn’t required!
- Can be replaced with a render function
- Also known as the ‘h(…)’ function
- ‘render()’: available in ‘script’ section
THE STARTING BLOCKS
BUILDING THE COMPONENT
1. Build the basic component
2. Split logic from rendering
3. Use our old view as a default
BRACE YOURSELVES, CODE AHOY!
BUILDING THE COMPONENT
<script>
export default {
data: () => ({
user: {
firstName: '',
lastName: ''
}
}),
watch: {
user: {
handler (val) {
this.$emit('input:user', val);
},
deep: true
}
},
methods: {
insertBob () {
this.user = {
firstName: 'Bob',
lastName: 'Marley'
};
}
}
};
</script>
<template>
<section class="my-user">
<h1>My User</h1>
<div class="my-user__input">
<label for="firstname">First Name</label>
<input type="text" id="firstname" v-model="user.firstName">
</div>
<div class="my-user__input">
<label for="lastname">Last Name</label>
<input type="text" id="lastname" v-model="user.lastName">
</div>
<button @click="insertBob()">Insert Bob</button>
</section>
</template>
BUILDING THE COMPONENT <script>
export default {
data: () => ({
scopeData: {
user: {
firstName: '',
lastName: ''
}
}
}),
watch: {
'scopeData.user': { … }
},
methods: {
updateUser (data) { … },
insertBob () { … }
},
render () {
return this.$scopedSlots.default({
// TODO
});
}
};
</script>
<script>
export default {
data: () => ({
user: {
firstName: '',
lastName: ''
}
}),
watch: {
user: {
handler (val) {
this.$emit('input:user', val);
},
deep: true
}
},
methods: {
insertBob () {
this.user = {
firstName: 'Bob',
lastName: 'Marley'
};
}
}
};
</script>
BUILDING THE COMPONENT
<script>
export default {
data: () => ({
scopeData: {
user: {
firstName: '',
lastName: ''
}
}
}),
…
render () {
return this.$scopedSlots.default({
// DATA
...this.scopeData,
// ACTIONS
updateUser: this.updateUser,
insertBob: this.insertBob
});
}
};
</script>
WE’RE ALMOST THERE 🎉
BUILDING THE COMPONENT
1. Build the basic component
2. Split logic from rendering
3. Use our old view as a default
BUILDING THE COMPONENT
<template>
<section class="my-user">
<h1>My User</h1>
<div class="my-user__input">
<label for="firstname">First Name</label>
<input
type="text" id="firstname"
v-model="user.firstName">
</div>
<div class="my-user__input">
<label for="lastname">Last Name</label>
<input
type="text" id="lastname"
v-model="user.lastName">
</div>
<button @click="insertBob()">Insert Bob</button>
</section>
</template>
<template>
<section class="my-user">
<my-user-rl @input:user="$emit('input:user', $event)">
<template
v-slot:default="{
user,
updateUser,
insertBob
}">
<section>
<h1>My User</h1>
<div class="my-user__input">
<label for="firstname">First Name</label>
<input type="text" id="firstname"
:value="user.firstName"
@input="updateUser({ firstName: $event.target.value })" />
</div>
<div class="my-user__input">
<label for="lastname">Last Name</label>
<input type="text" id="lastname"
:value="user.lastName"
@input="updateUser({ lastName: $event.target.value })" />
</div>
<button @click="insertBob()">Insert Bob</button>
</section>
</template>
</my-user-rl>
</section>
</template>
BUILDING THE COMPONENT
<template>
<section class="my-user">
<my-user-rl @input:user="$emit('input:user', $event)">
<template
v-slot:default="{
user,
updateUser,
insertBob
}">
<section>
<h1>My User</h1>
<div class="my-user__input">
<label for="firstname">First Name</label>
<input type="text" id="firstname"
:value="user.firstName"
@input="updateUser({ firstName: $event.target.value })" />
</div>
<div class="my-user__input">
<label for="lastname">Last Name</label>
<input type="text" id="lastname"
:value="user.lastName"
@input="updateUser({ lastName: $event.target.value })" />
</div>
<button @click="insertBob()">Insert Bob</button>
</section>
</template>
</my-user-rl>
</section>
</template>
<my-user-rl @input:user="$emit('input:user', $event)">
<template
v-slot:default="{
user,
updateUser,
insertBob
}">
<section>
…
</section>
</template>
</my-user-rl>
BUILDING THE COMPONENT
<template>
<section class="my-user">
<my-user-rl @input:user="$emit('input:user', $event)">
<template
v-slot:default="{
user,
updateUser,
insertBob
}">
<section>
<h1>My User</h1>
<div class="my-user__input">
<label for="firstname">First Name</label>
<input type="text" id="firstname"
:value="user.firstName"
@input="updateUser({ firstName: $event.target.value })" />
</div>
<div class="my-user__input">
<label for="lastname">Last Name</label>
<input type="text" id="lastname"
:value="user.lastName"
@input="updateUser({ lastName: $event.target.value })" />
</div>
<button @click="insertBob()">Insert Bob</button>
</section>
</template>
</my-user-rl>
</section>
</template>
<input type="text" id="lastname"
:value="user.lastName"
@input="updateUser({ lastName: $event.target.value })" />
RENDERLESS RECAP
BUILDING THE COMPONENT
- We’ve got a logic-only component
- Reusable for other ‘views’
- Added a default sample layout
- Based on the same logic layer
📦 Wrap it up and ship it! 📦
WEBPACK TIME, YAY (?)
SHIPPING COMPONENTS
SHIPPING MADE EASY
SHIPPING COMPONENTS
1. SETUP PLUGIN 2. BUILD THE LIBRARY
🎉 ALL DONE 🎉
HEY, WHERE’S THE LINKS?!
ROUNDING UP
GitHub Project:
github.com/larsvanherk/vue-renderless-demo
Adam Wathan’s original post:
adamwathan.me/renderless-components-in-vuejs/
Get in touch:
- @LarsVHerk & @ToThePointIT
🎉 Thank you! 🎉
ToThePoint STS / Lars van Herk / 3 june, 2019

More Related Content

What's hot (20)

How to Build SPA with Vue Router 2.0
How to Build SPA with Vue Router 2.0
Takuya Tejima
 
Virtual Madness @ Etsy
Virtual Madness @ Etsy
Nishan Subedi
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
Rebecca Murphey
 
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Ryan Weaver
 
Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
andrewnacin
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4
Javier Eguiluz
 
Curso Symfony - Clase 2
Curso Symfony - Clase 2
Javier Eguiluz
 
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Eduardo Shiota Yasuda
 
YUI 3
YUI 3
Dav Glass
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JS
Nicolas Embleton
 
AngularJS Animations
AngularJS Animations
Eyal Vardi
 
SenchaCon 2016: Want to Use Ext JS Components with Angular 2? Here’s How to I...
SenchaCon 2016: Want to Use Ext JS Components with Angular 2? Here’s How to I...
Sencha
 
A New Baseline for Front-End Devs
A New Baseline for Front-End Devs
Rebecca Murphey
 
DrupalCon jQuery
DrupalCon jQuery
Nathan Smith
 
Academy PRO: React native - navigation
Academy PRO: React native - navigation
Binary Studio
 
Dependency Management with RequireJS
Dependency Management with RequireJS
Aaronius
 
Intro To Mvc Development In Php
Intro To Mvc Development In Php
funkatron
 
AngularJS.part1
AngularJS.part1
Andrey Kolodnitsky
 
Laravel 로 배우는 서버사이드 #5
Laravel 로 배우는 서버사이드 #5
성일 한
 
PHP MVC
PHP MVC
Reggie Niccolo Santos
 
How to Build SPA with Vue Router 2.0
How to Build SPA with Vue Router 2.0
Takuya Tejima
 
Virtual Madness @ Etsy
Virtual Madness @ Etsy
Nishan Subedi
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
Rebecca Murphey
 
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Ryan Weaver
 
Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
andrewnacin
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4
Javier Eguiluz
 
Curso Symfony - Clase 2
Curso Symfony - Clase 2
Javier Eguiluz
 
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Eduardo Shiota Yasuda
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JS
Nicolas Embleton
 
AngularJS Animations
AngularJS Animations
Eyal Vardi
 
SenchaCon 2016: Want to Use Ext JS Components with Angular 2? Here’s How to I...
SenchaCon 2016: Want to Use Ext JS Components with Angular 2? Here’s How to I...
Sencha
 
A New Baseline for Front-End Devs
A New Baseline for Front-End Devs
Rebecca Murphey
 
Academy PRO: React native - navigation
Academy PRO: React native - navigation
Binary Studio
 
Dependency Management with RequireJS
Dependency Management with RequireJS
Aaronius
 
Intro To Mvc Development In Php
Intro To Mvc Development In Php
funkatron
 
Laravel 로 배우는 서버사이드 #5
Laravel 로 배우는 서버사이드 #5
성일 한
 

Similar to Using Renderless Components in Vue.js during your software development. (20)

09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
Igor Bronovskyy
 
Using RequireJS with CakePHP
Using RequireJS with CakePHP
Stephen Young
 
Love at first Vue
Love at first Vue
Dalibor Gogic
 
Modular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJS
Gunnar Hillert
 
A re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbai
Praveen Puglia
 
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Luciano Mammino
 
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Codemotion
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
Alessandro Molina
 
AngularJS Basic Training
AngularJS Basic Training
Cornel Stefanache
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can e big
Andy Peterson
 
Angular server side rendering - Strategies & Technics
Angular server side rendering - Strategies & Technics
Eliran Eliassy
 
AngularJS Internal
AngularJS Internal
Eyal Vardi
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJS
Antonio Peric-Mazar
 
Building and deploying React applications
Building and deploying React applications
Astrails
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-sense
Ben Lin
 
Getting Started with React v16
Getting Started with React v16
Benny Neugebauer
 
Introduction to angular js
Introduction to angular js
Marco Vito Moscaritolo
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
Alive Kuo
 
Vue routing tutorial getting started with vue router
Vue routing tutorial getting started with vue router
Katy Slemon
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
Igor Bronovskyy
 
Using RequireJS with CakePHP
Using RequireJS with CakePHP
Stephen Young
 
Modular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJS
Gunnar Hillert
 
A re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbai
Praveen Puglia
 
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Luciano Mammino
 
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Codemotion
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
Alessandro Molina
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can e big
Andy Peterson
 
Angular server side rendering - Strategies & Technics
Angular server side rendering - Strategies & Technics
Eliran Eliassy
 
AngularJS Internal
AngularJS Internal
Eyal Vardi
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJS
Antonio Peric-Mazar
 
Building and deploying React applications
Building and deploying React applications
Astrails
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-sense
Ben Lin
 
Getting Started with React v16
Getting Started with React v16
Benny Neugebauer
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
Alive Kuo
 
Vue routing tutorial getting started with vue router
Vue routing tutorial getting started with vue router
Katy Slemon
 
Ad

Recently uploaded (20)

Reimagining Software Development and DevOps with Agentic AI
Reimagining Software Development and DevOps with Agentic AI
Maxim Salnikov
 
Software Engineering Process, Notation & Tools Introduction - Part 3
Software Engineering Process, Notation & Tools Introduction - Part 3
Gaurav Sharma
 
GDG Douglas - Google AI Agents: Your Next Intern?
GDG Douglas - Google AI Agents: Your Next Intern?
felipeceotto
 
wAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptx
SimonedeGijt
 
dp-700 exam questions sample docume .pdf
dp-700 exam questions sample docume .pdf
pravkumarbiz
 
Artificial Intelligence Applications Across Industries
Artificial Intelligence Applications Across Industries
SandeepKS52
 
Women in Tech: Marketo Engage User Group - June 2025 - AJO with AWS
Women in Tech: Marketo Engage User Group - June 2025 - AJO with AWS
BradBedford3
 
FME as an Orchestration Tool - Peak of Data & AI 2025
FME as an Orchestration Tool - Peak of Data & AI 2025
Safe Software
 
Porting Qt 5 QML Modules to Qt 6 Webinar
Porting Qt 5 QML Modules to Qt 6 Webinar
ICS
 
Open Source Software Development Methods
Open Source Software Development Methods
VICTOR MAESTRE RAMIREZ
 
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
WSO2
 
Milwaukee Marketo User Group June 2025 - Optimize and Enhance Efficiency - Sm...
Milwaukee Marketo User Group June 2025 - Optimize and Enhance Efficiency - Sm...
BradBedford3
 
OpenTelemetry 101 Cloud Native Barcelona
OpenTelemetry 101 Cloud Native Barcelona
Imma Valls Bernaus
 
Neuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
Neuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
alexandernoetzold
 
UPDASP a project coordination unit ......
UPDASP a project coordination unit ......
withrj1
 
Advanced Token Development - Decentralized Innovation
Advanced Token Development - Decentralized Innovation
arohisinghas720
 
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
Aarno Aukia
 
Plooma is a writing platform to plan, write, and shape books your way
Plooma is a writing platform to plan, write, and shape books your way
Plooma
 
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Puppy jhon
 
Microsoft Business-230T01A-ENU-PowerPoint_01.pptx
Microsoft Business-230T01A-ENU-PowerPoint_01.pptx
soulamaabdoulaye128
 
Reimagining Software Development and DevOps with Agentic AI
Reimagining Software Development and DevOps with Agentic AI
Maxim Salnikov
 
Software Engineering Process, Notation & Tools Introduction - Part 3
Software Engineering Process, Notation & Tools Introduction - Part 3
Gaurav Sharma
 
GDG Douglas - Google AI Agents: Your Next Intern?
GDG Douglas - Google AI Agents: Your Next Intern?
felipeceotto
 
wAIred_RabobankIgniteSession_12062025.pptx
wAIred_RabobankIgniteSession_12062025.pptx
SimonedeGijt
 
dp-700 exam questions sample docume .pdf
dp-700 exam questions sample docume .pdf
pravkumarbiz
 
Artificial Intelligence Applications Across Industries
Artificial Intelligence Applications Across Industries
SandeepKS52
 
Women in Tech: Marketo Engage User Group - June 2025 - AJO with AWS
Women in Tech: Marketo Engage User Group - June 2025 - AJO with AWS
BradBedford3
 
FME as an Orchestration Tool - Peak of Data & AI 2025
FME as an Orchestration Tool - Peak of Data & AI 2025
Safe Software
 
Porting Qt 5 QML Modules to Qt 6 Webinar
Porting Qt 5 QML Modules to Qt 6 Webinar
ICS
 
Open Source Software Development Methods
Open Source Software Development Methods
VICTOR MAESTRE RAMIREZ
 
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
WSO2
 
Milwaukee Marketo User Group June 2025 - Optimize and Enhance Efficiency - Sm...
Milwaukee Marketo User Group June 2025 - Optimize and Enhance Efficiency - Sm...
BradBedford3
 
OpenTelemetry 101 Cloud Native Barcelona
OpenTelemetry 101 Cloud Native Barcelona
Imma Valls Bernaus
 
Neuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
Neuralink Templateeeeeeeeeeeeeeeeeeeeeeeeee
alexandernoetzold
 
UPDASP a project coordination unit ......
UPDASP a project coordination unit ......
withrj1
 
Advanced Token Development - Decentralized Innovation
Advanced Token Development - Decentralized Innovation
arohisinghas720
 
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
Aarno Aukia
 
Plooma is a writing platform to plan, write, and shape books your way
Plooma is a writing platform to plan, write, and shape books your way
Plooma
 
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Puppy jhon
 
Microsoft Business-230T01A-ENU-PowerPoint_01.pptx
Microsoft Business-230T01A-ENU-PowerPoint_01.pptx
soulamaabdoulaye128
 
Ad

Using Renderless Components in Vue.js during your software development.

  • 1. Vue.js Renderless Components It’s like advanced internet Legos! ToThePoint STS / Lars van Herk / 3 june, 2019
  • 2. 1. Build a standard, feature-rich base component 2. Separate the view from the logic 3. Slap it into a publishable library WHAT’CHA GONNA DO? INTRODUCTION We’re gonna do some Vue.
  • 3. WHY SO COMPLICATED? INTRODUCTION Every app works differently - “Our date pickers don’t look like that!” - Tweaking a prebuilt component’s layout is hard or impossible - Either accept it, or rebuild it
  • 4. WHAT DO WE NEED FOR THIS? INTRODUCTION Slots. Scoped Slots. https://vuejs.org/v2/guide/components-slots.html
  • 5. <template> <section class="my-alert"> <slot name="title"> <h1>This will be the default title!</h1> </slot> <slot v-bind:person="person"> Hello, {{ person.name }}! </slot> </section> </template> <template> <div id="app"> <my-alert :person="outerPerson"> <template v-slot:title> <h1>I'm going to replace the default!</h1> </template> </my-alert> </div> </template> <template> <section class="my-alert"> <h1>I'm going to replace the default!</h1> Hello, Bobby! </section> </template> MyAlert.vue App.vue Rendered Output INTRODUCTION
  • 6. RENDERING ALL THE THINGS! INTRODUCTION - Template part of SFC isn’t required! - Can be replaced with a render function - Also known as the ‘h(…)’ function - ‘render()’: available in ‘script’ section
  • 7. THE STARTING BLOCKS BUILDING THE COMPONENT 1. Build the basic component 2. Split logic from rendering 3. Use our old view as a default BRACE YOURSELVES, CODE AHOY!
  • 8. BUILDING THE COMPONENT <script> export default { data: () => ({ user: { firstName: '', lastName: '' } }), watch: { user: { handler (val) { this.$emit('input:user', val); }, deep: true } }, methods: { insertBob () { this.user = { firstName: 'Bob', lastName: 'Marley' }; } } }; </script> <template> <section class="my-user"> <h1>My User</h1> <div class="my-user__input"> <label for="firstname">First Name</label> <input type="text" id="firstname" v-model="user.firstName"> </div> <div class="my-user__input"> <label for="lastname">Last Name</label> <input type="text" id="lastname" v-model="user.lastName"> </div> <button @click="insertBob()">Insert Bob</button> </section> </template>
  • 9. BUILDING THE COMPONENT <script> export default { data: () => ({ scopeData: { user: { firstName: '', lastName: '' } } }), watch: { 'scopeData.user': { … } }, methods: { updateUser (data) { … }, insertBob () { … } }, render () { return this.$scopedSlots.default({ // TODO }); } }; </script> <script> export default { data: () => ({ user: { firstName: '', lastName: '' } }), watch: { user: { handler (val) { this.$emit('input:user', val); }, deep: true } }, methods: { insertBob () { this.user = { firstName: 'Bob', lastName: 'Marley' }; } } }; </script>
  • 10. BUILDING THE COMPONENT <script> export default { data: () => ({ scopeData: { user: { firstName: '', lastName: '' } } }), … render () { return this.$scopedSlots.default({ // DATA ...this.scopeData, // ACTIONS updateUser: this.updateUser, insertBob: this.insertBob }); } }; </script>
  • 11. WE’RE ALMOST THERE 🎉 BUILDING THE COMPONENT 1. Build the basic component 2. Split logic from rendering 3. Use our old view as a default
  • 12. BUILDING THE COMPONENT <template> <section class="my-user"> <h1>My User</h1> <div class="my-user__input"> <label for="firstname">First Name</label> <input type="text" id="firstname" v-model="user.firstName"> </div> <div class="my-user__input"> <label for="lastname">Last Name</label> <input type="text" id="lastname" v-model="user.lastName"> </div> <button @click="insertBob()">Insert Bob</button> </section> </template> <template> <section class="my-user"> <my-user-rl @input:user="$emit('input:user', $event)"> <template v-slot:default="{ user, updateUser, insertBob }"> <section> <h1>My User</h1> <div class="my-user__input"> <label for="firstname">First Name</label> <input type="text" id="firstname" :value="user.firstName" @input="updateUser({ firstName: $event.target.value })" /> </div> <div class="my-user__input"> <label for="lastname">Last Name</label> <input type="text" id="lastname" :value="user.lastName" @input="updateUser({ lastName: $event.target.value })" /> </div> <button @click="insertBob()">Insert Bob</button> </section> </template> </my-user-rl> </section> </template>
  • 13. BUILDING THE COMPONENT <template> <section class="my-user"> <my-user-rl @input:user="$emit('input:user', $event)"> <template v-slot:default="{ user, updateUser, insertBob }"> <section> <h1>My User</h1> <div class="my-user__input"> <label for="firstname">First Name</label> <input type="text" id="firstname" :value="user.firstName" @input="updateUser({ firstName: $event.target.value })" /> </div> <div class="my-user__input"> <label for="lastname">Last Name</label> <input type="text" id="lastname" :value="user.lastName" @input="updateUser({ lastName: $event.target.value })" /> </div> <button @click="insertBob()">Insert Bob</button> </section> </template> </my-user-rl> </section> </template> <my-user-rl @input:user="$emit('input:user', $event)"> <template v-slot:default="{ user, updateUser, insertBob }"> <section> … </section> </template> </my-user-rl>
  • 14. BUILDING THE COMPONENT <template> <section class="my-user"> <my-user-rl @input:user="$emit('input:user', $event)"> <template v-slot:default="{ user, updateUser, insertBob }"> <section> <h1>My User</h1> <div class="my-user__input"> <label for="firstname">First Name</label> <input type="text" id="firstname" :value="user.firstName" @input="updateUser({ firstName: $event.target.value })" /> </div> <div class="my-user__input"> <label for="lastname">Last Name</label> <input type="text" id="lastname" :value="user.lastName" @input="updateUser({ lastName: $event.target.value })" /> </div> <button @click="insertBob()">Insert Bob</button> </section> </template> </my-user-rl> </section> </template> <input type="text" id="lastname" :value="user.lastName" @input="updateUser({ lastName: $event.target.value })" />
  • 15. RENDERLESS RECAP BUILDING THE COMPONENT - We’ve got a logic-only component - Reusable for other ‘views’ - Added a default sample layout - Based on the same logic layer 📦 Wrap it up and ship it! 📦
  • 16. WEBPACK TIME, YAY (?) SHIPPING COMPONENTS
  • 17. SHIPPING MADE EASY SHIPPING COMPONENTS 1. SETUP PLUGIN 2. BUILD THE LIBRARY 🎉 ALL DONE 🎉
  • 18. HEY, WHERE’S THE LINKS?! ROUNDING UP GitHub Project: github.com/larsvanherk/vue-renderless-demo Adam Wathan’s original post: adamwathan.me/renderless-components-in-vuejs/ Get in touch: - @LarsVHerk & @ToThePointIT
  • 19. 🎉 Thank you! 🎉 ToThePoint STS / Lars van Herk / 3 june, 2019