Best Practices for Writing Vue Apps — Error Prevention
Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.
In this article, we’ll look at how to write Vue apps in an easy to maintain and performant fashion by looking at some best practices.
Component Style Scoping
The styles in the App
component should be global, but the style code for the remaining components should be scoped.
This creates less styling conflicts between components.
For instance, we can write the following code given that App
is the root component:
App.vue
:
<template>
<div id="app">
<AppTodo/>
</div>
</template><script>
import AppTodo from "./components/AppTodo";export default {
name: "App",
components: {
AppTodo
}
};
</script><style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
}
</style>
components/AppTodo.vue
:
<template>
<p>{{todo}}</p>
</template><script>
export default {
name: "AppTodo",
data() {
return {
todo: "eat"
};
}
};
</script><style scoped>
p {
color: red;
}
</style>
In the code above, we have the style for p in AppTodo
scoped to the component itself, so it won’t be available to anything outside.
On the other hand, the style in App
isn’t scoped, so it’s applied everywhere.
Private Property Names
We should use module scoping to keep private functions inaccessible from the outside. If that’s not possible, we should use the $_
prefix for custom private properties in anything that shouldn’t be considered public.
For example, we can write the following to indicate that a mixin method is a private method:
const mixin = {
methods: {
$_task() {
return "eat";
}
}
};new Vue({
el: "#app",
mixins: [mixin]
});
In the code above $_task
is a private method as indicated by the $_
prefix.
If we use modules, we can also write the following code to keep a function private:
mixin.js
:
const eat = () => "eat";const mixin = {
methods: {
task() {
return eat();
}
}
};export default mixin;
App.vue
:
<template>
<div id="app">{{task()}}</div>
</template><script>
import mixin from "./mixin";export default {
name: "App",
mixins: [mixin]
};
</script>
The code above has the eat
private function in mixin.js
. Then we just import the mixin
while keeping eat
private since we didn’t export it.
Whenever a build system is available to concatenate files, each component should be in its own file.
We should keep components in their own file so that we can find a component more quickly when we need to read or edit it.
For instance, we write the following code to separate components into files:
app-bar.js
:
Vue.component("app-bar", {
template: "<p>bar</p>"
});
app-foo.js
:
Vue.component("app-foo", {
template: "<p>foo</p>"
});
index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<app-foo></app-foo>
<app-bar></app-bar>
</div>
<script src="app-bar.js"></script>
<script src="app-foo.js"></script>
<script src="index.js"></script>
</body>
</html>
The code above includes one component definition in each file. Then we reference them in our template.
Single file components can only contain one component, so they’re always one component per file.
Filenames of single-file components should either be always PascalCase or always kebab-case.
Single file components can be both PascalCase or kebab-case. We should stick with one to keep everything consistent.
Base components (a.k.a. presentational, dumb, or pure components) that apply app-specific styling and conventions should all begin with a specific prefix, such as Base
, App
, or V
.
Base components are the components that lay the foundation for consistent styling and behavior in our app.
They only contain HTML elements, other base components, and 3rd party UI components. They never contain any global state.
This naming scheme groups all the base components together. It also prevents us from having to choose between arbitrary prefix for simple component wrappers.
Therefore, we should stick with one prefix for naming the components.
For example, a good naming scheme would be as follows:
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseInput.vue
Components that should only ever have a single active instance should begin with the The
prefix, to denote that there can be only one.
This naming scheme lets everyone know that the component is only used in once per page.
They don’t accept any props. For instance, we may have the following file names for our components:
components/
|- TheHeader.vue
|- TheFooter.vue
Conclusion
If we follow some naming conventions like prefixing base components with Base
and single instance components with The
, then a lot of confusion will be eliminated, making our Vue code more maintainable.
Styles should be scoped in any component other than App
so that we won’t have any issues with conflicting styles.