VueJs Style Guide

  1. File name must be lowercase and kebab case always.
# BAD
appTable.vue
StaticMap.vue

# GOOD
app-table.vue
static-map.vue
  1. Components name must be lowercase and kebab case always and equal to the file name (see rule #1)
// BAD
export default {
  name: 'AppTable',
};
// GOOD
export default {
  name: 'app-table',
};
  1. The name attribute must be the first attribute in the component. ALWAYS.
// BAD
export default {
  methods,
  watch,
  data
  computed,
  name: 'app-table',
};
// GOOD
export default {
  name: 'app-table',
  data,
  watch,
};
  1. All the functions of a vue component must be declared outside the component definition
// BAD
export default {
  name: 'app-table',
  data() {},
  methods: {
    myMethod() {},
  },
  computed: {
    myComputed() {},
  },
  watch: {
    name: () => {},
  },
};
// GOOD
function data() {}

function myComputed() {}

function myMethod() {}

function name() {}

export default {
  name: 'app-table',
  data,
  methods: {
    myMethod,
  },
  computed: {
    myComputed,
  },
  watch: {
    name,
  },
};
  1. Prefer shortcuts like @ or : over v-bind and v-on
<!-- BAD -->
<input v-on:change="onChange" />
<button v-bind:disabled="isDisabled">Submit</button>
<!-- GOOD -->
<input @change="onChange" />
<button :disabled="isDisabled">Submit</button>
  1. All components must use the scoped attribute in the style section. The only exception is the root component App.
<!-- BAD -->
<template>
  <button class="button">Submit</button>
</template>

<style>
.button {
  border: none;
  border-radius: 2px;
}
</style>
<!-- GOOD -->
<template>
  <button class="button">Submit</button>
</template>

<style scoped>
.button {
  border: none;
  border-radius: 2px;
}
</style>
  1. Use $ as a preffix for private properties
// BAD
import Vue from 'vue';
Vue.userInfo = { id: 1, name: 'Cosme Fulanito' };
// GOOD
import Vue from 'vue';
Vue.$userInfo = { id: 1, name: 'Cosme Fulanito' };
  1. Never put logic inside templates, use methods/computed instead.
<!-- BAD -->
<template>
  <div v-if="someArray.length > 0">
  </div>
</template>
<!-- GOOD -->
<template>
  <div v-if="hasValues">
  </div>
</template>

<script>
// computed
function hasValues() {
  return this.someArray.length > 0;
}
</script>
  1. Always use v-key together with v-for directive
<!-- BAD -->
<ul v-for="item in items">
<!-- GOOD -->
<ul v-for="item in items" :key="item">
  1. Avoid using v-if within v-for
<!-- BAD -->
<ul v-for="user in users" v-if="user.active" :key="user.id">
</ul>
<!-- GOOD -->
<ul v-for="user in filteredUsers" :key="user.id">
</ul>

<script>
function filteredUsers() {
  return this.users.filter(u => u.active);
}

export default {
  name: 'user-list',
  computed: {
    filteredUsers,
  },
};
</script>
  1. Use filters whenever you want to present the value in a different way but without changing the original value.
<!-- BAD -->
<td>
  {{ amount }}
</td>

<script>

function created() {
  this.amount = this.amount.toFixed(2);
}

export default {
	created,
}
</script>
<!-- GOOD -->
<td>
	{{ amount | round }}
</td>

<script>

function round(value) {
  return value.toFixed(2);
}

export default {
  filters: {
    round,
  },
};
</script>
  1. Always use classes over any other kind of css selectors for scoped components
<!-- BAD -->
<template>
	<button>Submit</button>
</template>

<style scoped>
button {
	background-color: peru;
	padding: 20px;
}
</style>
<!-- GOOD -->
<template>
	<button class="btn">Submit</button>
</template>

<style scoped>
.btn {
	background-color: peru;
	padding: 20px;
}
</style>
  1. Inside a vue component always put the template, script and style tag in that order.
<!-- BAD -->
<script>
</script>
<style>
</style>
<template>
</template>
<!-- GOOD -->
<template>
</template>

<script>
</script>

<style lang="scss" scoped>
</style>