gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
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 this 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.
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.
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); | |
}, | |
}); |
Tip
For Vue 3, the code should look like this:
import { createApp } from 'vue';
import App from './pages/products';
createApp(App).mount('#app');
That feels good! Let's try it: move over, refresh and... it still works!
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 |
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.
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.
I was getting the same error as below so I changed package.json to:
"vue": "2.6.11",
"vue-loader": "15.9.1",
"vue-template-compiler": "2.6.11",
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",
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",
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!
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 <a href="https://github.com/parcel-bundler/parcel/issues/1490">github</a>
Now everything work
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!
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<br />
Could you tell me what I am doing wrong?
Cheers and Thanks!
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
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!
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.
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?
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.
// package.json
{
"devDependencies": {
"@symfony/webpack-encore": "^0.30.0", // 0.30.2
"axios": "^0.19.2", // 0.19.2
"bootstrap": "^4.4.1", // 4.5.0
"core-js": "^3.0.0", // 3.6.5
"eslint": "^6.7.2", // 6.8.0
"eslint-config-airbnb-base": "^14.0.0", // 14.1.0
"eslint-plugin-import": "^2.19.1", // 2.20.2
"eslint-plugin-vue": "^6.0.1", // 6.2.2
"regenerator-runtime": "^0.13.2", // 0.13.5
"sass": "^1.29.0", // 1.29.0
"sass-loader": "^8.0.0", // 8.0.2
"vue": "^2.6.11", // 2.6.11
"vue-loader": "^15.9.1", // 15.9.2
"vue-template-compiler": "^2.6.11", // 2.6.11
"webpack-notifier": "^1.6.0" // 1.8.0
}
}
Also got the "Syntax Error: TypeError: Cannot read property 'parseComponent' of undefined" error. This fixed it for me in case anyone else gets it. This change is in package.json and was made to match the value for vue-template-compiler in package.json
Old Value
"vue": "2.5",
New Value
"vue": "^2.6.12",
Then run yarn install