What's up?
I'll be giving a talk at Vue.JS Live on April 25th.
You can check it out here: https://vuejslive.com/
Other than that, enjoy your tips and the rest of your week!
— Michael
null
Context-aware components are "magical" — they adapt to what's going on around them automatically, handling edge cases, state sharing, and more.
There are 3 main types of context-aware components, but configuration is the one I find most interesting.
When you break up a large component into smaller ones, they often still need to share state.
Instead of pushing that work on whoever's consuming the components, you can make this happen "behind the scenes."
To give you more flexibility, you may break up a Dropdown
component into Select
and Option
components. But to make it easier to use, the Select
and Option
components share the selected
state with each other:
<!-- Used as a single component for simplicity --><Dropdown v-model="selected" :options="[]" /><!-- Split up for more flexibility --><Select v-model="selected"><Option value="mustard">Mustard</Option><Option value="ketchup">Ketchup</Option><div class="relish-wrapper"><Option value="relish">Relish</Option></div></Select>
Sometimes component behaviour needs to change based on what's going on in the rest of the application. This is often done to automagically handle edge cases that would otherwise be annoying to deal with.
A Popup
or Tooltip
should reposition itself so it doesn't overflow out of the page. But if that component is inside a modal, it should move, so it doesn't overflow out of the modal.
This can be done automagically if the Tooltip
knows when it's inside a modal.
You already create context-aware CSS, applying different styles based on what's happening in parent or sibling elements.
.statistic {color: black;font-size: 24px;font-weight: bold;}/* Give some separation between statsthat are right beside each other */.statistic + .statistic {margin-left: 10px;}
CSS variables let us push this further, allowing us to set different values in different parts of the page.
If you want some styles to apply specifically to slot content, you can do that with the :slotted
pseudo-selector:
<style scoped>/* Add margin to <p> tags within the slot */:slotted(p) {margin: 15px 5px;}</style>
You can also use :global
to have styles apply to global scope, even within the <style scoped>
block:
<style scoped>:global(body) {margin: 0;padding: 0;font-family: sans-serif;}</style>
Of course, if you have lots of global styles you want to add, it's probably easier to just add a second <style>
block:
<style scoped>/* Add margin to <p> tags within the slot */:slotted(p) {margin: 15px 5px;}</style><style>body {margin: 0;padding: 0;font-family: sans-serif;}</style>
Check out the docs for more info.
Scoped CSS is fantastic for keeping things tidy and not accidentally bleeding styles into other parts of your app.
But sometimes, you need to override the styles of a child component and break out of that scope.
Vue has a :deep
selector just for this:
<style scoped>/* Override CSS of a child componentwhile keeping styles scoped */.my-component :deep(.child-component) {font-size: 24px;}</style>
In Vue 2 this has a slightly different syntax depending on which CSS pre-processor you're using:
<style scoped>/* When using SASS */.my-component ::v-deep .child-component {font-size: 24px;}/* Everything else */.my-component >>> .child-component {font-size: 24px;}</style>
Yes, I have previously covered why you shouldn't do this, but overriding styles can be the best solution (we don't believe in "best practices" here).
Vite has taken web development tooling to a new level.
This article explores all of the different tools Vite uses and interacts with, and shows just how much it affects the web development community.
It's very cool to see a project that started out in Vue-land gain wide adoption like this!
Check it out here: The Vite Ecosystem
"Bad programmers worry about the code. Good programmers worry about data structures and their relationships." — Linus Torvalds
The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬
Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.
If you have multiple levels of nested slots, it's possible to have defaults at each level:
<!-- Parent.vue --><template><Child><slot>We're in the Parent!</slot></Child></template>
<!-- Child.vue --><template><div><slot>We're in the Child!</slot></div></template>
The slot content provided at the highest point in the hierarchy will override everything below it.
If we render Parent
, it will always display We're in the Parent
. But if we render just the Child
component, we get We're in the Child!
.
And if the component rendering the Parent
component provides slot content, that will take precedence over everything:
<!-- Grandparent.vue --><template><Parent>Haha this content rules them all!</Parent></template>
p.s. I also have four products/courses: Clean Components Toolkit, Vue Tips Collection 2, Mastering Nuxt 3, and Reusable Components