Appearance
🔥 (#80) Component Metadata
September 2022
Hey!
This week I started recording the first batch of Mastering Nuxt 3 videos.
It's been awhile since I did lots of screencasting, so it's taking some time to find my rhythm again, but so far so good!
Enjoy these tips, and have a great week!
—Michael
🔥 Don't Override Component CSS
It can be really tempting to quickly modify a component's CSS from outside the component. If all you need is a slight modification, it seems harmless — but it's not.
Let's say you have a normally blue button, but you need it to be green in this specific case. You can override the background colour from the parent component like this:
<template>
<button class="green">Make this button green</button>
</template>
<style>
.green.button {
background: green;
}
</style>
This does work, but it's very fragile and prone to breaking.
What if the class name changes?
What if the HTML of the component is modified?
Anyone making changes to the button component will have no idea that this component's background colour is overridden. They won't know to update this component too.
Instead, we can just extend the functionality of the button component. That way, we keep all of the code that modifies the button inside the button component.
Here, we can add a is-green prop to the button component:
<template>
<button is-green>Make this button green</button>
</template>
<style>
/* No extra styles needed! */
</style>
Adding to the component itself makes it easier for anyone else who might need this button to be green in the future!
I've created a demo showing the original component and the new one with the added prop: https://codesandbox.io/s/wizardly-aryabhata-kn37d?file=/src/components/Button.vue
🔥 Component Metadata
Not every bit of info you add to a component is state. For example, sometimes, you need to add metadata that gives other components more information.
For example, if you want this layout to know how many columns each widget should take up, you can add that directly on the component as metadata:
export default {
name: "LiveUsersWidget",
// Just add it as an extra property
columns: 3,
props: {
// ...
},
data() {
return {
//...
};
},
};
You'll find this metadata as a property on the component:
import LiveUsersWidget from "./LiveUsersWidget.vue";
const { columns } = LiveUsersWidget;
You can also access the metadata from within the component through the special $options property:
export default {
name: "LiveUsersWidget",
columns: 3,
created() {
// `$options` contains all the metadata for a component
console.log(`Using ${this.$options.metadata} columns`);
},
};
Just keep in mind that this metadata is the same for each component instance and is not reactive.
Other uses for this include (but are not limited to):
- Keeping version numbers for individual components
- Custom flags for build tools to treat components differently
- Adding custom features to components beyond computed props, data, watchers, etc.
- and many more I can't think of!
See a live example here: https://codesandbox.io/s/vue-metadata-bew9j?file=/src/App.vue
📜 Coding Better Composables: Options Object (1/5)
I teamed up with Vue Mastery to create this series on coding better composables.
In this series we cover five different patterns.
For each, we show how you can implement it and then we see it in action with a composable from VueUse.
This first article is on using an options object to easily configure the behaviour of your composable.
Read it here: Coding Better Composables: Options Object (1/5)
💬 Data structures
"Bad programmers worry about the code. Good programmers worry about data structures and their relationships." —Linus Torvalds
🧠 Spaced-repetition: Async Without Await
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.
Using async logic with the composition API can be tricky at times.
We need to put things in the correct order, or the await keyword will mess things up with our reactivity.
But with the Async Without Await pattern, we don’t need to worry about all of this:
const title = ref("Basic Title");
// We can place this async function wherever we want
const { state } = useAsyncState(fetchData());
const betterTitle = computed(() => `${title.value}!`);
Here’s how this works:
- We hook up all of our refs synchronously
- Updates happen asynchronously in the background
- Because of reactivity, everything “just works”
Here’s a basic sketch of what the useAsyncState composable from VueUse is doing to implement this:
export default useAsyncState(promise) {
// 1. Create state ref synchronously
const state = ref(null);
const execute = async () => {
// 3. Reactivity will update this when it resolves
state.value = await promise;
}
// 2. Execute promise asynchronously in the background
execute();
return state;
}
p.s. I also have three courses: Vue Tips Collection, Reusable Components and Clean Components
来源
原文 https://michaelnthiessen.com/weekly-080-september-28/
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。