This Vue is a Javascript framework for building web apps. As with other frameworks, it allows using reusable components. Check how to use components in Vue
Previously I showed you how to get started with Vue, and I have promised that there will be a second part, and here you go!
Spoiler alert: there will even be a third series, but to the point!
So since we know the basics of Vue, we now have to dig into the Vue platform to create a custom component. We first create a component representing every player in our football (soccer??) team. We learn several basic concepts throughout the process, like calling components within another component, sending the data to the component via props, or using a provide/inject approach.
Components Basics
Components are reusable Vue instances. In the App that I started work on in the last article, there is the main component: App.vue.
Any other components accept the same properties as the root component: data, computed, methods, watch, etc.
Three parts of a component in Vue
Single-file component vue file comprises three pieces: HTML syntax to determine the visual view for the component. JavaScript provides a list of properties for creating the component, using standard JavaScript module syntax exports in JS. Style sheets are used in defining the best user interfaces.
You have to make a new file (typically in the components folder). Let’s name this file: PlayerCard.vue.
First, add a template section with HTML elements:
Export Vue components
To be honest, for a long time, I thought that I needed to add another section beneath the Templates section: and add an export object, like this:
But it is not necessary. You can have components only with the template section. Anyway, typically, you have more sophisticated components in apps, so it’s good to add an export default object with a name property.
How to import Vue components
Since we have exported components, we can use them in another place. In this case, we are going to import the PlayerdCard Vue component into the App component. To do so, let’s:
Import child components into parent components inside script tags
Register child component in a parent component
We need to let the App component know that it can use the PlayerdCard component. There is a components property that is responsible for registering components:
FINALLY. Use child component to render a child component template.
To render the PlayerCard component, you must put a custom element inside the App component template. We imported the component as PlayerCard, so this is the name of the custom element:
Global and local components
We registered globally our first component in App.vue, a root component. This is a typical approach, but sometimes you have specific components used in a minor part of the App.
Vue allows you to register components in other components. So you can register the component in the PlayerCard component instance, and you can use it and in any children of it then.
It means that the component is registered locally, and it will not be available in parent components - in our case, in the app component object.
Component communication
The PlayerdCard component is working, but it’s not too helpful. Let’s add some content to it:
A player object is used in many places, but the component object does not include player data. How to pass player data to the component?
Introducing props
To pass data to the components, you can use props. Props are HTML attributes that can be, let’s say, moved to the component scope.
First, we need to define that the PlayerCard component can receive a player prop:
Then we can pass the player prop to the PlayerCard in App.vue
A player is an array defined in data of the App component:
To make the example more accurate, let’s iterate through the players’ array using v for directive and display all players on the screen:
Supported props
Above, we passed an object as a prop, but you can also give other types. Take a look at prop types that Vue supports:
-
String
-
Number
-
Boolean
-
Array
-
Object
-
Date
-
Function
-
Symbol
Props validation
When I registered a prop in the PlayerCard component, I just pasted a name into the props array:
but there is an option to validate props. Take a look:
Now, the component expects that player will be an object, so any other type passed to the component will throw a warning in the console.
Also, you can specify that prop is required:
Default value:
Besides, there are more options. Please follow Vue docs to meet them all. The last thing that I want to do here is repeating Vue docs.
After this step, the App renders two players:
Custom events: child-parent communication
Our very first Vue component works, but there are some bugs. When I click on “add to transfer list,” I see the error in the console:
That happens because, in the PlayerCard, we don’t have the toggleForSale function. That function is in the scope of the App Vue component.:
Anyway, that function is outdated. It worked in the case when we had one player. Now we have an array of players, so we have to update the toggleForSale function to make that possible.
Now the function receives the playerId parameter to identify which player should be modified, but still – the toggleForSale function is in the scope of the App component. Is it possible to call this method from other Vue components? Especially from child components?
There is a way to do that: custom events!
Defining custom events
To define an event, you should add it to the emits array like this:
Technically, it’s not obligatory but is a good practice to define events because then it’s more clear to understand how components work.
The next step is emitting our custom event when the user clicks on the button:
Lastly, we have to listen to this event in the App component:
For the @toggle-for-sale custom event, I bound toggleForSale function available in App.js, and now the functionality works as expected.
Validating custom events
As props, the custom events can be validated. It’s possible by defining emits not as an array but as objects. Each property of that object is a custom event name, and it’s a validation function:
Prop drilling problem
If you came here from React, you are probably familiar with a common problem called: props drilling. If not, let me explain quickly by example.
We are going to add two components to the PlayerCard component:
-
PlayerData
-
PlayerAttributes
before we start implementing those components, we add some additional data to our players:
The PlayerData component
This component renders some information about a player like a birthday, growth, and better leg.
Let’s import it and register in the playerCard Vue component:
Now we can use it in the template section:
The PlayerAttributes component
This component will be pretty the same. The difference is that it renders other data:
Note: for now, those components looks the same, but in the future, I am going to add more logic there, so don’t worry, I have an idea 😆
The last thing in this step is registering, importing, and using the new component in PlayerCard.
The final code of the PlayerCard component:
This is rendered playerCard in the browser:
I wanted to show you a props drilling problem if you forgot, and here you go. We have the PlayerdCard component that receives the player as a prop, and that component has children: PlayerData and PlayerAttributes components that also receive the player as a prop.
Moreover, PlayerCard’s child components also can have children that need a player. A prop drilling problem is about passing props from parent to child. It can be problematic and frustrating if you have a big tree of components.
In React application, there is a way to handle that differently – by using Context. In vue, there is something familiar.
provide/inject as a solution
Instead of passing props to every child component, you can provide data in the parent component and inject this data into children. Take a look:
Then in any child, you can inject players:
Once I injected player into the PlayerData and PlayerAttributes component, I can remove the player prop from them in the PlayerCard component:
The App still works, but data is passed differently.
Dynamic components
Last thing that I want to show you are dynamic components. Now we have two components in the PlayerCard component: PlayerData and PlayerAttributes, and they are rendered on the screen. I would like to have something like tabs and the possibility to change the active tab. Then only one component corresponding to chosen tab will be visible.
First, create a nav for tabs:
I bound the selectTab method to click event so let’s create this method:
Besides, add a new data property with the selectedTab field:
Lastly, let’s render our components dynamically by adding a
Thanks to that, we can render dynamic components based on data property like this example. When a property is changed, Vue dynamically switch component and render them.
Complete code including dynamic components:
The App looks like this for now:
It isn’t lovely:😎 but, don’t worry – next time, I will show you how to style Vue applications.
Summary
This Vue is a Javascript framework for building web apps. As with other frameworks, it allows using reusable components. Thanks to that, frontend development and building single-page applications are easy and efficient.
Today I showed you basics about components:
-
how to create and register vue component
-
how components communicate with other components
-
how to use props
-
what is a prop drilling problem
-
how to use provide/inject mechanism
-
how to use dynamic components
-
and so on