Single File Components In VueJS

Single File Components In VueJS

Now that we have our vue cli build environment set up and working nicely, let’s try building some components! We’ll go through the process of getting App.vue set up as the main file which will simply make use of components to display things. We can begin by just rendering some html from the main App.vue file, then we will export that markup to it’s own component. From there, we’ll see how to make use of that component. Once we have the most basic component working, we’ll add some behavior to that component. Lastly, we’ll see how to render more than one of the single file components to demonstrate it’s re-usability and the fact that each instance of the component has it’s own data which can be updated independently from any other of that rendered component.

The index.html file

The index.html file which loads the entire application will use this markup below. It’s super simple, we just import Bootstrap to make things look pretty, set a div with the #app id, and load the build.js file which get’s created upon running an npm run build command.

The main.js file

Render HTML From The Template

We can start by adding some very simple html markup to the App.vue file to demonstrate how Vue will render markup. At this point we’ll have no dynamic data or behavior, just static html.

Now we can visit the command prompt and run npm run dev to build the source.

C:\localdev\vue-cli>npm run dev

> vue-cli@1.0.0 dev C:\localdev\vue-cli
> cross-env NODE_ENV=development webpack-dev-server --open --hot

Project is running at http://localhost:8080/
webpack output is served from /dist/
404s will fallback to /index.html
Hash: 48898b00668fb0a0bc94
Version: webpack 3.11.0

Voila! We have some html rendered via Vue in our browser.
html rendered by vue

Extract HTML To A Single File Component

Now, we can extract this markup to it’s own component. Let’s see how to do that. First off, let’s create a new file paying attention to the naming convention of the file. We will use Uppercase for each word of the file name with no spaces or hyphens. We’ll also add a components folder to hold the new component.
single file component example

Components Must Have One Root Element

With the new BootstrapCard.vue file created, we can now begin populating the file with some markup. The first thing we need to be aware of is that in the <template> section of .vue file, there can be only one root element. What does that mean? In simple terms, it means you need a wrapping div around any markup you want Vue to render for you. Note the highlighted <div> here.

We can take the markup that was in App.vue between the <template> tags, and move that markup into <template> tag of this new BootstrapCard.vue file.

This is great, but nothing works as of yet. Let’s continue.

Components Must Export An Object

In the <script> section of the component, you must export an object in JavaScript. This represents the Vue instance of this component.

Using Your New Component

Now we can navigate back to the App.vue file and try to make use of the new component. How can we do that?

Import a component

In order to use the new component you created in a different .vue file, you first need to import that component like so.

Components Must Be Registered

Now that the component is imported, you need to register the component for use. Registering a component can be done globally in the main.js file or locally in the .Vue file where you would like to make use of the component. This is an example of registering the component locally.

Use The New Component

The last step, is to include the new html tag that represents the new component we created in the <template> section. But what is the tag we use? Well here is a little magic happening behind the scenes by Vue. Since we followed the convention of upper case of each word on the naming of the component, i.e., BootstrapCard, this automatically translates to a tag of <bootstrap-card>. In fact, we can see our IDE already recognizes the new component.
vue component in phpstorm

Congratulations! Your first single file component is now working! It has no dynamic data or behavior, but it is in fact working and it is a great step in understanding how single file components work from scratch in Vue.
html rendered by vue

Adding Behavior To Your Single File Component

The first section got us up and running with a static Vue component. Of course, we want to add some dynamic data and behavior to that component so that is what we will do in this second section. First off though, let’s just center the component in the page using Bootstrap 4’s new flexbox features.

Looks pretty good!
bootstrap flexbox centering

Using The data() function

Now we want to start populating the data of the component dynamically. In other words, we want to use the actual data contained in Vue to determine the contents of the component rather than hardcoding those values in. So in the <script> section of BootstrapCard.vue, we will now set up the dynamic data like so.

Important! In single file components, the data() function must actually be a function that returns an object rather than an object itself. Why? This is so that everytime you make use of the component elsewhere, it will have access to it’s own data – not a shared instanced of data. In other words, if you have four bootstrap cards on the page, each one will have it’s own data. It sounds simple, but this is a really important point.

Data binding with v-text vs v-html

Now, we want to bind that data to the markup in the <template> area of the component. Notice that the <h5> tag and the <p> tag no longer have any text between the tags. What we are doing is dynamically binding the data we just set up in the data() function, and now *that* will be what populates the tags. In the card title, we will be able to use text. In the card paragraph we can use text or html.

Now the card is being rendered with dynamic data.
bootstrap flexbox centering

Modifying Data With Methods

Now we want to actually add some behavior to the component. How about when we click the button, we change the title of the component? For this, we will set up a new setTitle() method in the methods object like we see here. What it will do when triggered is to take the new string and assign it to the thecardtitle property which will in turn update the UI in real time.

Triggering A Method With A Click Event

Right now there is no way to actually trigger the setTitle() function. For this, we need to set up an event listener on our button. When we click that button, we want the setTitle() function to run. Here is the markup to add to the <template> section to make that work. We use the @click event listener and set it’s attribute value to “setTitle”.

Ah ha! With that update our component now has both dynamic data and dynamic behavior. Sweet!
dot vue file in action

Using v-for on a component

Remember we said that each instance of a component will have it’s own data? Let’s prove that. In the App.vue file, we can use the v-for directive to loop out 2 card components like so. This should now output two components to the browser and they should both work independently of each other. In other words, clicking one button will only effect that particular title on that particular component.

And yes, this is working as intended.
independent behavior of components

The Final Component

That pretty much sums it up for getting a super basic single file component set up in Vue. Below we’ll simply add one more method and click handler to also update the body of the card. We’ll use some html on the body since we used the v-html tag like we saw.



Try It Out!

Included here is the actual built files which are rendering the component and providing the associated behavior.

Single File Components In VueJS Summary

Single File Components are super powerful in VueJs and likely the way you will want to make use of Vue. Using this approach removes several limitations that you might see when not using Single File Components. For example, without single file components you may run into these challenges.

  • Global component registrations force unique names for every component
  • String templates have no syntax highlighting and use ugly slashes for multiline HTML (YUCK)
  • No CSS support means that while HTML and JavaScript are modularized into components, CSS is left out entirely
  • No build step restricts us to HTML and ES5 JavaScript, rather than ES6 and Babel

To gain these benefits, you need a build development workflow. For that, the Vue Cli is your best friend! Learn more about this type of approach right at the Vue website.