Nested Slots Vue

Nested Slots Vue 4,8/5 7928 votes
You block advertising 😢
Would you like to buy me a ☕️ instead?
  1. Nested Slots Vueling
  2. Jsx Slot
  3. Vue Component Slot
  4. Nested Slots Vue App

Note that nested paths that start with / will be treated as a root path. This allows you to leverage the component nesting without having to use a nested URL. As you can see the children option is just another Array of route configuration objects like routes itself. Therefore, you can keep nesting views as much as you need.

  • However, the content of a button can be more than just plain text — it might contain any HTML markup, for example an icon or image, or even a nested Vue.js component. Also, using a slot more closely resembles the standard HTML tag, so such code is easier to write and understand.
  • Vue Nested Slots, sjoerd slot zaanstad, accommodation at crown casino melbourne, most successful roulette strategy Find new Online Casino Bonuses from the best casinos around – No Deposit, Bonus Free Spins and Cash Bonus Deals to play Vue Nested Slots slot games and pokies for real money.

One of my biggest aha moments in the last couple of months was when I realized that Loose Coupling makes the most sense when dependencies trigger side-effects.

So my first principle for when to use Dependency Injection is:

Always inject dependencies that trigger side effects.

I recently discovered that we can let the file structure of our projects guide us to find out which components we should inject into other components via slots and which components we can import directly.

Never import components from a parent directory.

But keep in mind that in programming, there are no absolute truths. So take always and never with a grain of salt. Depending on several factors, e.g., your application’s size and complexity, Dependency Injection might be overkill.

If you sometimes struggle to determine if you should use a slot or import a component directly, this article is for you. We will learn how we can utilize the file structure to help us decide when to use slots.

Let the File Structure Determine Whether We Should Use Slots

Imagine the following tree structure:

If we want to build a card component that displays product details, what we shouldn’t do, is modify the BaseCard component.

Instead we apply the Inversion of Control principle.

Slots in Vue.js components are a form of Dependency Injection; instead of tightly coupling a specific component by importing and rendering it directly inside another component, we can use a slot to decouple both components.

Generic base components should never rely on components with specific functionality. But it’s not always that straightforward. In some instances, you might wonder if you should apply the rules of loose coupling and use slots or if tightly coupling two or more components is the better approach.

We can use the file structure to make it easier to develop rules that guide us in making decisions about tight and loose coupling. In the example above, we can see that BaseCard is nested one level deeper than ProductDetails. If we follow this pattern with other types of components, we can make the following rule:

Never import components from a parent directory.

For example, the BaseCard component is not allowed to import any parent directory component. But the ProductDetails component is allowed to import any Base component it wants.

Domain-Driven Design

Suppose we want to build our applications using the Domain-Driven Design paradigm; in that case, we can create a modules directory containing components and all other code specific to a particular module or feature.

All components at the root level of our file tree are allowed to use both Base components and components inside the modules directory (another possible name is features). But Base components are only allowed to import components within their scope. If a module needs the BaseCard component, we need to inject it via a slot or other means of dependency injection.

That way, we get the following benefits:

  • completely decoupled components;
  • shareable modules (across projects or micro frontends);
  • components are explicit about which dependencies they need;
  • components do not rely on a specific implementation (style) of a dependency but only on a specific interface.

The three types of components:

  • Base components are the most generic building blocks of our applications. They should be easily reusable across projects. (e.g. BaseButton, BaseCard, BaseDialog)
  • Root level components can be generic or specific, but they are always project-specific. (e.g. TheHeader, TheSidebar, PromoBlackFriday)
  • Module components are specific to a certain feature (e.g. ProductList, ArticleBody, ShoppingCartTotal).

Do you want to learn more about advanced Vue.js techniques?

Register for the Newsletter of my upcoming book: Advanced Vue.js Application Architecture.

Exceptions

If we decide to follow this principle, I’d say that we should always follow the rule of not importing components from a parent directory except for Base components. In the case of those generic building blocks, we might decide to break the rule. But only if it makes sense for the app we’re building. By default, there should not be an exception for Base components.

Exceptions, in the other direction, are always acceptable. If it makes sense for an individual component to provide slots for other components on the same level or even nested deeper than the component, it is ok to do so.

Keep in mind that exceptions are always hard to document, and especially for larger teams, too many exceptions can lead to chaos.

Wrapping It Up

Following this principle can be helpful for certain types of projects. But keep in mind that this highly depends on the circumstances. You can decide to use it because it helps you and your team make architecture decisions faster, but you can also determine that it is not worth it for the project you’re working on.

With so many different ways to share data across components, you should know which technique is best for your situation. Let’s analyze three of the most common ways to pass data in VueJS.

Sharing data across components is one of the core functionalities of VueJS. It allows you to design a more modular project, control data scopes, and create a natural flow of data across your app.

Unless you’re creating your entire Vue app in one component (which wouldn’t make any sense), you’re going to encounter situations where you need to share data between components.

By the end of this tutorial, you will know three ways to get this done.

  • Using props to share data from parent to child,
  • Emitting custom events to share data from child to parent,
  • Using Vuex to create an app-level shared state.

Okay — let’s get right into it!

Building An App With Nuxt

With Spotify, your friends can check out what you’re jamming to. What if the rest of the Internet could experience your algo-rhythm, too? Learn how to compose your own app to share what you’re listening to on Spotify using Vue.js and Nuxt. Read more →

1. Using Props To Share Data From Parent To Child

VueJS props are the simplest way to share data between components. Props are custom attributes that we can give to a component. Then, in our template, we can give those attributes values and — BAM — we’re passing data from a parent to a child component!

For example, let’s say we’re working on a user profile page and want to have a child component accept a username prop. We’ll need two components.

Nested
  1. The child component accepting the prop, let’s call this AccountInfo.vue.
  2. The parent component passing the prop, let’s call this ProfilePage.vue.

Inside AccountInfo.vue, we can declare the props it accepts using the props option. So, inside the component options, let’s make it look like the following.

Then, to actually pass the data from the parent (ProfilePage.vue), we pass it like a custom attribute.

Now if we load our page, we can see that our AccountInfo component properly renders the value passed in by its parent.

As when working with other VueJS directives, we can use v-bind to dynamically pass props. For example, let’s say we want to set the username prop to be equal to a variable. We can accomplish this by using shorthand for the v-bind directive (or just : for short). The code would look a little like this:

This means that we can change our data and have any child props using that value will also update.

Tip: Always Verify Your Props

Nested slots vue js

If you’re looking to write clearer Vue code, an important technique is to verify your props. In short, this means that you need to specify the requirements for your prop (i.e. type, format, and so on). If one of these requirements is not met (e.g. if the prop is passed an incorrect type), Vue will print out a warning.

Let’s say we want our username prop to only accept Strings. We would have to modify our props object to look like this:

Verifying props is essential when working in large-scale Vue apps or when designing plugins. It helps ensure that everyone is on the same page and use props the way that they were intended.

For a full list of the verifications we can include on props, I’d definitely recommend checking out the official documentation for an in-depth review.

Tip: Follow Prop Naming Conventions

According to the VueJS style guide, the best way to name your props is by using camelCase when declaring them in your script and kebab-case when referencing them in template code.

The reasoning behind this is actually quite simple. In Javascript, camelCase is the standard naming convention and in HTML, it’s kebab-case.

So, Vue recommends that we stick to the norms of each language. Thankfully, Vue is able to automatically convert between the two styles so there’s no additional setup for developers.

2. Emitting Events To Share Data From Child To Parent

Now that we have data passing down the hierarchy, let’s pass it the other way: from a child component to a parent. We can’t use props, but we can use custom events and listeners.

Every Vue instance can call a .$emit(eventName) method that triggers an event. Then, we can listen for this event in the same way as any other, using the v-on directive.

Creating a Custom Event

Nested Slots Vueling

Let’s build on our user profile example by adding a button that changes the username. Inside our child component (AccountInfo.vue), let’s create the button.

Then, when this button is clicked, we’ll emit an event called changeUsername.

Inside the parent, we handle this event and change the user.username variable. Like we were discussing earlier, we can listen to events using the v-on directive or '@' for short.

Let’s try it out. You should see that when you click the button, the username changes to 'new name'.

Tip: Custom Events Can Accept Arguments

The most common use case for passing arguments to your events is when you want a child component to be able to set a specific value for its prop. You never want to directly edit the value of a prop from the component itself.

However, luckily we can use pass arguments with our custom events to make the parent component change values.

Let’s say we want to modify the changeUsername event so that we can pass it a value.

The $emit method takes an optional second parameter for arguments. So all we do is add our new username value after the name of our event.

Then, in our parent component, we can either access these values inline by using a special $event variable, or we can write a handler method that takes a parameter.

3. Using Vuex To Create An Application-Level Shared State

Okay — we know how to share data between parents/children, but what about other components? Do we have to create an extremely complex hierarchy system if we want to pass data?

Thankfully not. The wonderful Vuex state management library has been simplifying developers' lives for years. In short, it creates a centralized data store that is accessible by all components.

In the methods we used previously (props / emitting events), each component has its own data state that we then share between components. However, Vuex lets us extract all the shared data into a single state that each component can access easily. This shared state is called a store.

Let’s try it out.

Because Vuex is separate from the core code of Vue, we’ll first have to install and import it into our project. First, we’ll have to run npm install vuex --save inside our project CLI.

Then, create a src/store folder with an index.js file that contains the following code.

To include this in our root Vue instance, we have to import our store/index.js file and pass it in our Vue constructor.

Accessing Vue Store Inside Components

Since we added our Vuex store onto our root Vue instance, it gets injected into all of the root’s children. If we want to access the store from a component, we can via this.$store.

Now, let’s dive into the specifics of each of the four parts of a Vuec store.

1. State

The Vuex state is an object that contains application-level data. All Vue instances will be able to access this data.

Drive

For our store, let’s create a user object that stores some more user profile data.

We can access this data inside any instance component like this.

2. Getters

We use Vuex getters to return a modified value of state data. A good way to think of getters is to treat them like computed properties. For example, getters, like computed properties, cache their results and only re-evaluate when a dependency is modified.

Building onto our earlier store, let’s say we want to make a method that returns a user’s first name based off the full name attribute.

Vuex getter properties are available to components on the store.getters object.

Tip: Know the Default Getter Arguments

By default, Vuex getters accept two arguments.

  1. state — the state object for our application;
  2. getters — the store.getters object, meaning that we can call other getters in our store.

Every getter you declare will require the first state argument. And depending on how you design your code, your getters can reference each other using the second 'getters' argument.

Let’s make a last name getter that simply removes our first name value from our full name state property. This example would require both the state and getters objects.

Tip: Pass Custom Arguments to Vuex Getters

Another cool feature of getters is that we can pass them custom arguments by making our getter return a method.

3. Mutations

Mutations are the only way to properly change the value of the state object. An important detail to note is that mutations must be synchronous.

Like getters, mutations always accept the Vuex state property as their first argument. They also accept a custom argument — called a payload — as the second argument.

Jsx Slot

For example, let’s make a mutation to change a user’s name to a specific value.

Then, we can call this method from our component using the store.commit method, with our payload as the second argument.

More often than not, you are going to want your payload to be an object. Not only does this mean that you can pass several arguments to a mutation, but also, it makes your code more readable because of the property names in your object.

There are two different ways to call mutations with a payload.

  1. You can have the mutation type as the first argument and the payload as the second.
  2. You can declare pass a single object, with one property for the type and another for the payload.

There isn’t a real difference between how the two work so it’s totally up to personal preference. Remember that it’s always best to be consistent throughout your entire project, so whichever one you choose, stick with it!

4. Actions

In Vuex, actions are fairly similar to mutations because we use them to change the state. However, actions don’t change the values themselves. Instead, actions commit mutations.

Also, while Vuex mutations have to be synchronous, actions do not. Using actions, we can call a mutation after an API call, for example.

Whereas most of the Vuex handlers we’ve seen accept state as their main parameter, actions accept a context object. This context object allows us to access the properties in our Vuex store (e.g. state, commit, getters).

Here’s an example of a Vuex action that waits two seconds and then commits the changeName mutation.

Inside our components, we use the store.dispatch method in order to run our function. We pass arguments just like we did with mutations. We declare the type and we pass any custom arguments in the second argument.

Wrapping Up

Now, you should know three different ways to share data across components in VueJS: props, custom events, and a Vuex store.

I hope this tutorial helped give you some more insight into some different Vue methods and best practices. Let me know how you’ve implemented them into your projects!

Vue Component Slot

Further Reading

If you’re interested in going even deeper into the technical side/capabilities of each technique, here are some great places to start.

  • Vuex Official Guide website
  • VueJS Docs for Props and Custom Events
  • “WTF Is Vuex? A Beginner’s Guide To Vue’s Application Data Store,” Anthony Gore, Vue.js Developers

Nested Slots Vue App

(dm, yk, il)