Vue is one of the most rapidly growing JavaScript frameworks in today’s world. Described as an “Intuitive, Fast, and Composable” MVVM for building interactive interfaces, Vue has become every developer’s favorite JavaScript framework for developing interactive web apps and interfaces. This is quite obvious with its 97K GitHub ⭐️ since its release in 2014.
Unlike Angular, which is based on the good old Model-View-Controller architecture, Vue follows a Model-View-View-Model system.
Another great thing about Vue is that it has single file components. This means that you can write the template
, the script
, and the style
in a single .vue
file.
<template>
<p>({greeting })</p>
</template>
<script>
module.exports = {
data: function () {
return {
greeting: 'Hello'
}
}
}
</script>
<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>
In this post, I will portray some of the best practices that you may want to keep in mind when building an advanced Vue App.
There are many different ways that you can choose from for creating a Vue App. If you are a newbie, you can check out out this JS Fiddle Hello World Example to try out Vue.
In this post I am going to use the Vue CLI to create a Vue Project. First, open a command terminal in your system and write the following command to install the Vue CLI:
$ npm install --global @vue/cli
You can now create a Vue project! So lets go ahead and do that:
$ vue create vue-app
$ cd vue-app
This will create a new Vue project called vue-app. You can name it something else if you want.
Take a look at the code snippet at the top of and you will see that you have a data
function that returns an object. If you want to pass any handlers, you would have to write a method
object.
vue-class-component
reduces the component development process by allowing developers to add data properties and handlers directly as properties to the class.
Open your project directory in a code editor (I ❤️ VS Code). In your src
folder, you will notice two files: App.vue
and main.js
.
Developers with prior experience in libraries like React
can say that the main.js
file is equivalent to React’s index.js
. Meaning this the actual file that gets launched when you run commands like yarn serve
or yarn build
.
Re-write the main.js
file with the following code:
import 'tailwindcss/dist/tailwind.css';
import Vue from 'vue';
import App from './App';
new Vue ({
el: '#app',
render: h => <App />,
});
main.js
Basically, we are first grabbing a div
element that has “app” as the id from the public/index.html
file and then we are rendering the App
component inside it.
You now need to create this App
component inside the App.vue
file. Open the App.vue
file and replace the default code with this:
<template>
<h1 @click="onClick">
{{message}}
</h1>
</template>
<script>
import Vue from 'vue';
import Component from 'vue-class-component';
export default Component({})(
class App extends Vue {
message = 'Batman';
onClick() {
this.message = 'Bruce Wayne';
}
}
);
</script>
App.vue
Here, I first have created a simple template
that has a div
with a message inside it. The script
imports the Vue
package and the Component
function from vue-class-component
. You also need to install this package in your project.
$ yarn add vue-class-component
Next, I am decorating the App
class with the Component
function. This function has an object that you can pass in options.
If you are using VS Code, you will see that you are now getting an error on App
. This is because VS Code by default does not accept experimental decorator. To solve this issue, create a new file called jsconfig.json
in the project’s root directory. Here, you are telling the Vue Compiler to allow experimental decorators in your code:
{
"compilerOptions": {
"experimentalDecorators": true
}
}
Reload the editor and you will see the error disappear!
Now we answer the question, “Why should I use vue-class-component
instead of Vue’s traditional components?”
In a traditional component, you are required to write a data
function that returns an object. To change anything in your component, you will then write methods
such an onClick
.
const TraditionalComp = {
data() {
return {message: "Batman"}
},
methods:{
onClick() {
this.message = "Bruce Wayne"
}
}
}
But in vue-class-component
, you directly write the onClick
method. All that’s left to do is link it to the template
. You can do this by writing @click="onClick"
inside the template’s h1
tag.
Run the Vue app using the yarn serve
command, and you will see it work like this:
You can also use vue-property-decorator
to define the properties directly on the class. And that too is done with a simple @Prop()
decorator. This method of prop declaration lets us keep our classes simple.
First, install the vue-property-decorator
package in your project:
$ yarn add vue-property-decorator
Another great thing about this package is that it also includes the vue-class-component
inside it. So you can instead import the Component
from the vue-property-decorator
package.
Inside the App.vue
file, re-write the code as shown below:
<template>
<h1 @click="onClick">
{{message}}
</h1>
</template>
<script>
import Vue from 'vue';
import {Component, Prop} from 'vue-property-decorator';
export default Component({})(
class App extends Vue {
@Prop({default: 'Batman'})
message;
onClick() {
this.message = 'Bruce Wayne';
}
}
);
</script>
App.vue
Here, I am first importing the Component
and Prop
from the vue-property-decorator
package. Then inside the App
class, I am using the @Prop
decorator to set the default value of the message
.
And that’s it! You are now passing the message
as prop to our code, and it also has a default value.
Vue’s slots
lets you tell your code where you want your content to be in the component. This may sound confusing now, so let’s see what slots
actually do for us with some coding.
Back in the main.js
file, re-write the code inside render
like this:
render: h => (
<App>
<h1>Superman</h1>
</App>
)
If you take a look at the app in your browser, you will see that nothing has changed. This is because you have not specified any place for the new text inside the template
in App.vue
file. This is where slots
come into play.
Inside App.vue
‘s template
, write two new slots
that wrap the original h1
tag.
<template>
<div>
<slot name="header"></slot>
<h1 @click="onClick">
{{message}}
</h1>
<slot name="footer"></slot>
</div>
</template>
Your app still won’t render the new text. That’s because the compiler now doesn’t know which slot to put the new text in. I want the text to be in the bottom slot. I have given this slot a name
of footer
.
Go to main.js
file, and add an attribute of slot="footer"
to the new text. This will then render the new text.
But your render
method is a bit unwieldy now. Let’s see how you can use slots
to take care of that.
You can also use slots
to create custom layouts that can be used to specify where each piece of your app or component should be placed.
Create a new file called Layout.vue
inside the src/components
folder. Inside this file, write a template
element as shown below:
<template>
<div>
<slot name="header"></slot>
<slot name="body"></slot>
<slot name="footer"></slot>
</div>
</template>
Next, go into the App.vue
file and delete everything inside the template
tag. Then, inside the script
tag, import the Layout.vue
that you just created, like this:
import Layout from './components/Layout';
You also need to tell the Component
decorator that you are using the Layout
as a component.
export default Component({
components: {Layout},
})
You can now use the Layout
as a component inside the template
tag. I am going to also add a few text tags.
<template>
<Layout>
<h1 slot="header">How To Build Vue Apps Like A Pro 😎</h1>
<h2 slot="body"> by Rajat S</h2>
<h3 slot="footer">Technical Content Writer</h3>
</Layout>
</template>
Make sure that you have added a slot
attribute with the appropriate name, else the text tags will not get rendered.
By combining your components with slots
, you can pass the component’s data into slot using slot-scope
. You can pass props down from Parent components to Child components without coupling them together.
Go to the App.vue
file and inside the template
tag, wrap the Layout
inside a Settings
tag.
<template>
<Settings>
<Layout slot-scope="{header}">
<h1 slot="header">{{header}}</h1>
<h2 slot="body"> by Rajat S</h2>
<h3 slot="footer">Technical Content Writer</h3>
</Layout>
</Settings>
</template>
Import the Settings
inside the script
tag,
import Settings from './components/Settings.vue';
Tell the Component
decorator that you are using Settings
as a component.
export default Component({
components: {Layout, Settings},
})
Now, you actually need to create the Settings
component. So go to src/components
and create a file named Settings.vue
. Write this code inside it:
<template>
<div>
<slot :header="header"></slot>
</div>
</template>
<script>
import Vue from 'vue';
import Component from 'vue-class-component';
export default Component({})(
class Settings extends Vue {
header = 'How To Build Vue Apps Like A Pro 😎';
}
);
</script>
Settings.vue
Inside the template
tag, I have a root div
that has slot
inside it. Inside this slot
, I’m binding :header
to header
.
Moving on to the script
tag, I am first importing the Vue
package and the Component
decorator from vue-class-component
package.
Then I create a Header
class inside the Component
decorator. This class contains the data that I want to pass on to the header prop.
Functional templates allows you to create a component that only has a template
tag and exposes the props
into the template.
Inside the src/components
folder, create a new file called Header.vue
write this code inside it:
<template functional>
<h1 slot="header">{{props.header}}</h1>
</template>
The term functional
here is used to indicate that this file only has a simple template
. Repeat this for Body.vue
and Footer.vue
files.
Return to the App.vue
file and re-write the template
like this:
<template>
<Settings>
<Layout slot-scope="{header, body, footer}">
<Header slot="header" :header="header"></Header>
<Body slot="body" :body="body"></Body>
<Footer slot="footer" :footer="footer"></Footer>
</Layout>
</Settings>
</template>
You also need to write the import statements for the Header
, Body
, Footer
inside the file’s script
tag:
import {Header, Body, Footer} from './components';
And tell the Component
decorator that you are using these as components.
export default Component({
components: {
Settings,
Layout,
Header,
Body,
Footer,
},
})
But the code still won’t work. Because the import statement that you just wrote is not entirely correct. To solve this issue, create a new file called index.js
inside src/components
.
export {default as Header} from ‘./Header.vue’;
export {default as Body} from ‘./Body.vue’;
export {default as Footer} from ‘./Footer.vue’;
With this, you have created Functional Templates in Vue that allows us to pass our props from a Parent component to a Child component, without having to write much code.
Vue is a software technology that is being widely used across the world for web development. Vue is actually a JavaScript framework with various optional tools for building user interfaces.
One of the main factor’s behind Vue’s success is that it is very easy to learn and it’s even easier to build awesome apps with it.
I hope this post helped you understand Vue better and how you can build better apps with it. Stay tuned for similar posts on Vue, React, and other popular frameworks/libraries. Feel free to comment and ask anything!
#vuejs #javascript #vue