Better late than never, right? I've got an article for you that I recently published: Make Your Components Easier to Think About. And as always, your tips. — Michael 🔥 Dynamic Directives Vue lets us use dynamic arguments with directives: <template> <WowSoDynamic v-bind:[somePropName]="somePropValue" v-on:[customEvent]="handleClick" /> </template>
When the argument evaluates to null , the attribute or event is removed. This makes a really convenient way of making them conditional: <!-- LinkComponent.vue --> <template> <a :href="url" v-bind:[targetAttr]="'_blank'" > <slot /> </a> </template> <script setup> import { computed } from 'vue'; const { newTab } = defineProps({ newTab: { type: Boolean, default: false, }, url: { type: String, required: true, }, }); // If newTab === false set this to null const targetAttr = computed(() => newTab ? 'target' : null); </script>
By using a computed prop, we set targetAttr to null if newTab is false . Either we add the target attribute with a value of _blank , or we don't add it. 🔥 Render Functions and Custom Component Options Vue's render functions and custom component options offer a powerful way to dynamically generate and control the rendering of components. For instance, you can conditionally render child components or slots based on certain criteria. Here's a basic render function that conditionally renders slots: return () => { const slots = useSlots(); const children = []; if (props.val && slots.true) { children.push(slots.true()); } else if (!props.val && slots.false) { children.push(slots.false()); } return children; };
Custom component options can be used to tag components with specific properties that can be checked during rendering. This is useful when you have a set of components and you want to treat some of them differently based on their role or type. For example, you can define a custom option in a child component: export default { props: ['if'], conditional: true, // Custom component option setup(props) { // ... }, };
And then in the parent component's render function, you can filter child components based on this custom option: const slots = useSlots(); const conditionalComponents = slots .default() .filter((el) => el.type.conditional); const children = [conditionalComponents];
This pattern is particularly useful when creating compound components that need to communicate and share state in a tightly coupled manner. It allows for a clean and declarative approach to rendering while maintaining flexibility and control over the component tree. 🔥 Custom Directives In script setup you can define a custom directive just by giving it a camelCase name that starts with v : <script setup> const vRedBackground = { mounted: (el) => el.style.background = 'red', } </script> <template> <input v-red-background /> </template>
export default { setup() { // ... }, directives: { redBackground: { mounted: (el) => el.style.background = 'red', }, }, }
Registering a directive globally: const app = createApp({}) // make v-focus usable in all components app.directive('redBackground', { mounted: (el) => el.style.background = 'red', })
And since a very common use case is to have the same logic for the mounted and updated hooks, we can supply a function instead of an object that will be run for both of them: <script setup> const vRedBackground = (el) => el.style.background = 'red'; </script> <template> <input v-red-background /> </template>
You can find more info on custom directives in the docs. 🎙️ #015 — Ten Years of Vue (with Evan You) This DejaVue episode is special - Alex and Michael meet up with the creator of Vue, Vite, and Rolldown, Evan You, and talk about the last ten years of Vue! Starting with how Vue.js started as a side project while Evan still worked at Google, Evan shares the story of how Vue.js came to be and how it evolved over the years. Interesting insights, such as why the Composition API was created and which initial problems should be solved with it, are shared in this episode. And to all that, questions from the Q&A were answered as well, touching on topics like petite-vue, if and how the Options API will persist, and how opinionated Vue.js is. After an hour of content and insights, the episode ends with a tiny cliffhanger, as Part Two of the conversation covering the future of Vue, possible Vue 4 features, Vapor mode, Vue 3.5, and more, will be released next week! Enjoy the episode! Watch on YouTube or listen on your favourite podcast platform. Chapters: In case you missed them: 📜 Async with Composition API In this article Anthony Fu takes us through a great technique for managing async behaviours with the composition API. It removes a lot of the complexity with async code, making it easier to think about and work with. Check it out here: Async with Composition API 📜 The Vite Ecosystem 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 📅 Upcoming Events Here are some upcoming events you might be interested in. Let me know if I've missed any! PragVue 2024 — (September 17, 2024) The first Czech Vue.js conference, taking place in Cinema City - Nový Smíchov Check it out here Vuejs.de Conf — (October 8, 2024 to October 9, 2024) A community-driven Vue conference in Germany. Listen to great talks from great speakers and meet the wonderful VueJS Community. Check it out here Vue Fes Japan 2024 — (October 19, 2024) Check it out here VueConf Toronto 2024 — (November 18, 2024 to November 20, 2024) My favourite Vue conference, in my own backyard! A three-day event with workshops, speakers from around the world, and socializing. Check it out here 💬 "Users" "There are only two industries that refer to their customers as 'users'." — Edward Tufte 🧠 Spaced-repetition: Recursive slots 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. I decided to see if I could make a v-for component using only the template. Along the way, I discovered how to use slots recursively, too. This is what the component looks like: <!-- VFor.vue --> <template> <div> <!-- Render the first item --> <!-- If we have more items, continue! But leave off the item we just rendered --> <v-for v-if="list.length > 1" :list="list.slice(1)" /> </div> </template>
If you wanted to do this with scoped slots — and why wouldn't you?! — it just takes a few tweaks: <template> <div> <!-- Pass the item into the slot to be rendered --> <slot v-bind:item="list[0]"> <!-- Default --> </slot> <v-for v-if="list.length > 1" :list="list.slice(1)" > <!-- Recursively pass down scoped slot --> <template v-slot="{ item }"> <slot v-bind:item="item" /> </template> </v-for> </div> </template>
Here is how this component is used: <template> <div> <!-- Regular list --> <v-for :list="list" /> <!-- List with bolded items --> <v-for :list="list"> <template v-slot="{ item }"> <strong></strong> </template> </v-for> </div> </template>
|
评论
发表评论