Adventures in Refactoring: Slots

Timmy Zhou
Jan 29 · 6 min read

While on my daily routine of browsing software internship positions, it finally got to the point where I had to stop myself from continuing to gloss over key words like “scalable”, “organized and readable“, and “high standards for clean code”.

Sooner or later, I was going to have to go through the icky-ness of upending the routine of slapping everything together and actually doing what I’m supposed to, so I decided to just dive right in. Clearly, just having a product that works wouldn’t be good enough for just about anybody else. Not surprisingly, once I got the hang of better ways to organize the codebase, adding new features became faster than if I had stuck to my old, comfortable habits.

I started off the process by typing in “best practices refactoring vue” into every developer’s best friend: google. After being scared away from a couple long form blogs, I come across a page that is quite readable and talks about slots. This was one of those concepts in Vue that I definitely remember trying hard to wrap my head around the first time I’d read the docs, but had since forgotten since I’d never used them until now. At this point, I got the gist that slots greatly helped to organize components, and make them as small as possible in order to promote reusability. Well that’s convenient! My components were a mess, and only one was being used across 2 or more pages. I’d definitely been using them wrong. Instead of reusability, I’d focused on just sticking whole page’s worth of code in there to avoid cluttering my parent component.

Here was my thought process from start to finish for the day:

  • What are slots? Oh it has to do with using multiple templates… oh wait so I’m not doing anything wrong by putting v-for loops in template tags(I’d long ago learned that v-for with a component wouldn’t work outside a template tag, so I’d copy and pasted the same format ever since without questioning). What does a template do again?… Wait it’s not a Vue only tag?? Ohh that makes a lot of sense (templates are rendered only when called by the script) Ok back to slots now… so it has something to do with being similar with props. Props I understand pretty well. So slots are only used when referenced by the parent component, otherwise a default is displayed. Okay… so the component is now smaller, but isn’t the parent component more bloated now? I thought that was what I didn’t want. Oh wait, components ARE supposed to be smaller, that’s how they can be reusable.
  • I’ve been purposefully trying to ignore this, and stick big chunks of code into components while making it seem like the parent was less bloated).

The next day, I felt like I had a better, but still vague grasp on slots, and when I tried explicitly writing down my impression, I found there were still gaps in my knowledge. I was still under the assumption that the child component would have a slot populated with information and then the parent would just grab that section. Basically the opposite of what it’s supposed to be.

Ultimately, this tutorial from Telerik, gave me the ah-ha moment. The Slot below isn’t populated with anything, rather the parent component is the one calling slice() and {{fruit.name}}. To make sure, I ran this example locally and commented out {{fruit.name}}. Lo and behold, the Slot was empty! Turns out the confusion I had before, had to do with a default value being passed between <slot> that would display if the parent didn’t specify a value.

Child
Child
Parent
Parent

The next piece of the puzzle that clicked was how the slot merely serves up bounded variable to the parent component to call (In this case fruit & slice) as SlotProps. My initial assumption was that :fruit and :slice represented two different slots. In the parent, I thought that even thought fruit and slice were passed in, only fruit was being used since it called the name attribute. I could see slice() being used, but couldn’t figure out how it all connected.

To test, I deleted slice from the <template> in parent, and somehow the button stopped working. Ah ok, so the bounded variables in <slot> must somehow act as keys that the <template> needs to register. It’s kind of like reverse props after props are passed in!

So in this example:

  • fruitOfTheNinja are passed to <FruitList> as “fruits”
  • “fruits” is iterated over to produce multiple instances of “fruit”
  • <FruitList> includes the slice() method
  • If this slot is to be used, pass “fruit” and “slice” up to the parent component, so they can be called successfully

Next up was fixing how I had been just dumping an entire separate page’s worth of code inside a component. It looked so clean at the time inside my parent component though!

Here’s less than half of what originally was in <MemberProfileGrid> (has been updated with correctly using slots)

It was pretty clear that I’d been using components wrong when I was able to copy and paste the whole component into its own separate page and have it run standalone without problem!

In my previous list of components, there are two instances where I decided to make a copy of a previous component, and proceed to make just one change. (I’m looking at you ProfileGrid2 and ListingGrid2).

Since these were literally 95% similar and 5% different, I realized I could just use slots to remedy the different section I needed to be displayed and keep the rest the same between both pages/components!

For Melacast, both paid members and regular users could view a grid of all listings posted by directors. The difference was that paid members could view further details, while regular users would be prompted to subscribe to see more. Both types of users could see a grid of listings with basic information like the Title, Date Range of filming, and it’s Cover Photo. This was kept the same between both pages and I just introduced 2 slots to handle the different response after clicking.

Easy Peasy!

What my components folder looks like now, down to 11 from 30+!

Yes I’m aware the naming convention is horrible, will change soon! 😅

Knowledge Foundation

Helping myself think smarter.

Knowledge Foundation

A blog for documenting my thought processes over the course of a project and how I can improve upon them in the future. Writing challenges me to build a “tree trunk’s foundation” [Tim Urban] of knowledge as I tackle new challenges.

Timmy Zhou

Written by

Knowledge Foundation

A blog for documenting my thought processes over the course of a project and how I can improve upon them in the future. Writing challenges me to build a “tree trunk’s foundation” [Tim Urban] of knowledge as I tackle new challenges.