Single File Component

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

As we've seen, it's totally possible to configure the Vue instance and put the template in the same file. But... this is going to get crazy as our app grows: can you imagine writing 100 lines of HTML inside this string... or more? Yikes! Fortunately, Vue solves in a unique, and pretty cool way: with single file components.

Inside the js/ directory create a new folder called pages/, and then a file called products.vue. We'll talk more about the directory structure we're creating along the way.

Notice that .vue extension: these files aren't really JavaScript, they're a custom format invented by Vue.

Creating the Single File Component

On top, add a <template> tag. Then, copy the h1 HTML from the original file, delete the template variable, and paste here.

<template>
<h1>Hello {{ firstName }}! Is this cooler?</h1>
</template>
... lines 4 - 14

Next, add a <script> tag. Anything in here is JavaScript and we'll export default an object that will hold our Vue options. Copy the data() function, delete it, and move it here.

... lines 1 - 4
<script>
export default {
data() {
return {
firstName: 'Ryan',
};
},
};
</script>

That's it! I know, the format is a bit strange, but it's super nice to work with. On top, the <template> section allows us to write HTML just like if we were in a Twig template. And below, the <script> tag allows us to set up our data, as well as any of the other options that we'll learn about. This is a fully-functional Vue component.

Using the Single File Component

Back in products.js, to use this, first, import it: import App - we could call that variable anything - from './pages/products. Thanks to Encore, we don't need to include the .vue extension.

... line 1
import App from './pages/products';
... lines 3 - 10

Now, inside of render, instead of worrying about compiling the template and all this boring, crazy-looking code, the App variable already has everything we need. Render it with return h(App).

... lines 1 - 3
new Vue({
el: '#app',
render(h) {
return h(App);
},
});

That feels good! Let's try it: move over, refresh and... it still works!

Adding a Component Name

From here on out, we're going to do pretty much all our work inside of these .vue files - called single file components. One option that we're going to add to every component is name: set it to Products. We could use any name here: the purpose of this option is to help debugging: if we have an error, Vue will tell us that it came from the Products component. So, always include it, but it doesn't change how our app works.

... lines 1 - 5
export default {
name: 'Products',
... lines 8 - 12
};
... lines 14 - 15

$mount() the Component

Before we keep working, there are two small changes I want to make to products.js. First, the el option: it tells Vue that it should render into the id="app" element on the page. This works, but you usually see this done in a different way. Remove el and, after the Vue object is created, call .$mount() and pass it #app.

... lines 1 - 3
new Vue({
render(h) {
return h(App);
},
}).$mount('#app');

I also like this better: we first create this Vue object - which is a template and set of data that's ready to go - and then choose where to mount it on the page.

Shorthand render() Method

Second, because the render() method only contains a return line, we can shorten it: render set to h => h(App).

... lines 1 - 3
new Vue({
render: (h) => h(App),
}).$mount('#app');

That's effectively the same: it uses the arrow function to say that render is a function that accepts an h argument and will return h(App). I'm mostly making this change because this is how you'll see Vue apps instantiated on the web.

Next, let's get to work inside our single file component: we'll add the HTML markup needed for our product list page and then learn how we can add styles.

Leave a comment!

  • 2020-07-27 Peter Kosak

    HI Sayil,

    had exactly the same issue. I have downloaded start code of tutorial and in package.json vue version is/was set to 2.5 but vue-template-compiler to ^2.6.11
    so all you need is just to change vue: to ^2.6.11 rerun yarn install and yarn watch and it should be fine

  • 2020-07-16 Steven

    Hi, it's work perfectly by replacing the "2.5" version of vue package by "^2.6.11".
    "vue-loader" is set to 15 so he's already using the latest version.

    It would be nice if wp-encore updated his installation message.

    Thanks for the solution!

  • 2020-06-30 Matias Jose

    Hey! I'd like to further comment on this:

    Different projects might have different requirements as to what to install in order for Vue to compile properly through Webpack. Also, when upgrading older versions of Vue to, say, 2.6.11, you might have special needs as well. But if you start from our project's starting point and follow our directions to the letter, you should have no problems with it!

    Having said that, if you find issues, please, let us know!

    In the future, encore might choose to install Vue 2.7 (when it's available) as its default Vue 2 version. There should be no problem there as well, but if there is, we'd also like to hear about it!

  • 2020-06-30 Matias Jose

    Hi, Alexei!

    Please try with these settings in your package.json and see if it works:


    "vue": "^2.6.11",
    "vue-loader": "^15.9.1",
    "vue-template-compiler": "^2.6.11",
  • 2020-06-29 Alexei Saron

    Uncaught Error: Module build failed (from ./node_modules/vue-loader/lib/index.js):
    TypeError: Cannot read property 'parseComponent' of undefined

    help me , please.


    resolved -> package.json

    "vue": "2.6.11",
    "vue-loader": "15",
    "vue-template-compiler": "2.6.11",
  • 2020-06-04 Matias Jose

    Hey Micka!

    Thanks for letting us know!

  • 2020-06-04 Micka Bup

    Hi guys,
    I had the same problem but changing vue and vue-template-compiler to "2.6.11" was not enough. I had to type :yarn add --dev @vue/component-compiler-utils@1.3.1 find on this github
    Now everything work

  • 2020-05-30 sayil aguirre

    Hi Matias,
    you where right, I had a look on my package.json file and changed the version of vue from 2.5 to 2.6.11 and then everything worked fine!
    Thanks for you help.

  • 2020-05-29 Matias Jose

    Hmm, hard to think of a reason! Did you config Encore for Vue 3 or Vue 2? what do your package.json and webpack.config.js files look like?

  • 2020-05-29 sayil aguirre

    Hi Matias,
    thanks for answering so quick!
    I tried this but I am still getting the error. I made sure that the vue-template-compiler was installed but still nothing. I ran yarn install after changing the version but I still get the same error. Could there be any other reason for this?
    Thanks in advance.

  • 2020-05-29 Matias Jose

    Hi Sayil!

    Please look at your package.json for vue-template-compiler. This might be an error where Yarn has installed a wrong version of it. You might be able to fix this by changing the version number from ^2.6.10 to 2.6.10 (remove the ^) and run Yarn again to update the package.

    This could also happen if vue-template-compiler is missing (i.e. you have forgotten to run yarn to install your packages in the first place)

    Let me know if this helps!

  • 2020-05-29 sayil aguirre

    Hi guys,
    I am having a problem with the single page component.
    I am getting an error in the products.vue file and I could not find a solution for this. This is the error I am getting.
    Syntax Error: TypeError: Cannot read property 'parseComponent' of undefined

    Could you tell me what I am doing wrong?

    Cheers and Thanks!