Skip to content

Vue Coding Style

Introduction

This guide includes Vue.js specific coding standards.

Component Structure

Section Order

vue
<template>
  <!-- template content -->
</template>

<script>
// script content
</script>

<style>
/* style content */
</style>

Component Naming

  • Use PascalCase
  • File name should match component name
  • Use meaningful names

Template

HTML Structure

  • Use semantic HTML
  • Use v-if instead of v-show for rare conditions
  • Use key for v-for

Example

vue
<template>
  <div class="user-profile">
    <h1 v-if="user.name">{{ user.name }}</h1>
    <ul>
      <li v-for="item in items" :key="item.id">
        {{ item.title }}
      </li>
    </ul>
  </div>
</template>

Script

Composition API

Preferably use Composition API:

vue
<script setup>
import { ref, computed, onMounted } from 'vue'

// reactive data
const count = ref(0)
const user = ref(null)

// computed properties
const doubleCount = computed(() => count.value * 2)

// methods
const increment = () => {
  count.value++
}

// lifecycle
onMounted(() => {
  // initialization
})
</script>

Options API

When using Options API:

vue
<script>
export default {
  name: 'ComponentName',
  props: {
    title: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      count: 0
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}
</script>

Props

Defining Props

javascript
props: {
  title: {
    type: String,
    required: true,
    default: ''
  },
  count: {
    type: Number,
    default: 0,
    validator: (value) => value >= 0
  }
}

Using Props

vue
<template>
  <div>
    <h1>{{ title }}</h1>
    <p>Count: {{ count }}</p>
  </div>
</template>

Events

Emitting Events

javascript
// in child component
const emit = defineEmits(['update', 'delete'])

const handleClick = () => {
  emit('update', { id: 1, value: 'new value' })
}

Listening to Events

vue
<template>
  <ChildComponent 
    @update="handleUpdate"
    @delete="handleDelete"
  />
</template>

Style

Scoped Styles

vue
<style scoped>
.component-name {
  color: var(--primary-color);
}

.component-name__element {
  margin: 1rem 0;
}
</style>

Global Styles

vue
<style>
/* only when needed */
</style>

Best Practices

Performance

  • Use v-memo for optimization
  • Use shallowRef for large data
  • Use defineAsyncComponent for lazy loading

Reusability

  • Small and reusable components
  • Use slots for flexibility
  • Use composables for shared logic

Testing

  • Test props and events
  • Test computed properties
  • Test lifecycle hooks