Slots, Scoped Slots, and Render Function
๐ Slots
๐ Scoped Slots
๐คฏ Render Function
๐คฏ Slots
๐คฏ Scoped Slots
๐ Render Function
I build interfaces on the web.
I'm on CodePen, Twitter and Instagram as @coltborg."I want to write code today that allows me to write less code tomorrow."
"Show examples of code I've written to help others build more reusable components."
Slots allow for fluid content
Scoped Slots allow for reusable functionality
Render function gives you the power of programmatic templating
(But can also be used for renderless components)
There are situations, where you really need the full programmatic power of JavaScript. Thatโs where you can use the render function, a closer-to-the-compiler alternative to templates.
๐ <template>
compiles to render functions under the hood.
โ๏ธ A way to write Vue with JSX
โ๏ธ Useful for functional (stateless) components.
// AnchoredHeading.vue
export default {
render: function (createElement) {
return createElement(
'h' + this.level, // tag name
this.$slots.default // array of children
)
},
props: {
level: {
type: Number,
required: true
}
}
};
A renderless component
What if you want to componentise functionality and define the markup uniquely?
The render function needs to return a VNODE.
{
name: 'SomeComponent',
render() {
return createElement('h1', this.blogTitle);
},
}
{
name: 'SomeComponent',
render() {
return this.$slots.default[0];
},
}
{
name: 'SomeComponent',
render() {
return this.$scopedSlots.default({
childData: this.childData,
childMethod: this.childMethod,
});
},
}
Vue implements a content distribution API thatโs modeled after the current Web Components spec draft, using the
element to serve as distribution outlets for content.
Slots are useful when you want to inject content in a specific place of a component.
Using Slots
Slot Text
Quick note, my-button
(kebab-case) and MyButton
(PascalCase) are both acceptable and are only truely different when using non-string templates.
Using Default Content
-
+
+ General Warning
+ Something not ideal is happening.
+
Using Named Slots
A warning message.
- A warning message.
+
๐ค
Test Label
-
+
// MyTransition.vue
/* MyTransition.vue */
Sometimes youโll want to provide a component with a reusable slot that can access data from the child component.
When you want a template inside of a slot to access data (or methods) from the child component.
With Scoped Slot Data
{{ slotProps.item.text }}
-
+
- {{ slotProps.item.text }}
+ {{ item.text }}
Popper
Encapsulating 3rd Party JavaScript
...
data() {
- return {};
+ return {
+ isOpen: false,
+ triggerEl: null,
+ popperEl: null,
+ };
},
+ mounted() {
+ this.triggerEl = this.$el.querySelector('[data-trigger]');
+ this.popperEl = this.$el.querySelector('[data-popper]');
+ },
...
// ...
{
methods: {
setupPopper() {
if (this.popper === undefined) {
this.popper = new Popper(this.triggerEl, this.popperEl, this.config);
} else {
this.popper.scheduleUpdate();
}
},
},
}
// ...
// ...
{
methods: {
// ...
open() {
if (this.isOpen) {
return;
}
this.isOpen = true;
this.$nextTick(() => {
this.setupPopper();
});
},
close() {
if (!this.isOpen) {
return;
}
this.isOpen = false;
},
},
}
// ...
Don't forget to ๐ฎ
// ...
{
data() {
// ...
},
beforeDestroy() {
if (!this.popper) {
return;
}
this.popper.destroy();
},
mounted() {
// ...
},
// ...
}
// ...
// ...
{
// ...
render() {
- return this.$scopedSlots.default({});
+ return this.$scopedSlots.default({
+ isOpen: this.isOpen,
+ open: this.open,
+ close: this.close,
+ });
},
}
Content of the popper goes here
Component Composition
Components In Components In Components
(Cue Inception Horns)
Tooltip
Hover activated, icon as trigger, dark popper, standard transition
Input Tooltip
Regex activated, input + validation as trigger, red popper, standard transition
Dropdown
Click activated, button as trigger, can close on outside click, menu appearance, standard transition
Resources