Reference Guide: Vue.js Single File Components

October 29, 2019

Create file Hello.vue

<template>
  <div>
    <div class="greet">Hello {{ item.name }} ({{ nameUpper }})</div>
    <div>
      <input v-model="nickName" placeholder="Nick name">
      Hi {{ nickName }}
    </div>
    <div>
      <button @click="increment">{{ count }}</button>
      <a href="#" @click.prevent="increment">{{ count }}</a>
    </div>
    <div>
    <a :href="url">Google</a> -
    <a :href="url + '?q=' + q">Query</a> -
    <a :href="buildUrl()">Build Query</a>
    </div>
  </div>
</template>

<script>
export default {
  name: 'hello',    // optional
  props: ['item'],
  data() {
    return {
      nickName: '',
      count: 0,
      url: 'https://www.google.com/search',
      q: 'hello'
    }
  },
  computed: {
    nameUpper() {
      return this.item.name.toUpperCase()
    }
  },
  methods: {
    increment() {
      this.count += 1
    },
    buildUrl() {
      return `${this.url}?q=${this.q}`
    }
  }
}
</script>

<style scoped lang="scss">
.greet {
  font-size: 2rem;
  font-weight: bold;
}
</style>

Single Root Elemnt

<template>
  <div>
    ...
  </div>
</template>

Styles

<template>
  <div class="greet">Hello {{ item.name }}</div>
</template>

<style scoped lang="scss">
.greet {
  font-size: 2rem;
  font-weight: bold;
}
</style>

NOTE: Use scoped: CSS will apply to elements of the current component only.

NOTE: lang="scss" to use Scss instead of CSS.

Passing Data via Props / Use Component

Pass in data from Parent

<template>
  <div>
    <hello :item="{name: 'Desmond', age: 40}" />
  </div>
</template>

<script>
// @ is an alias to /src
import Hello from '@/components/Hello.vue'

export default {
  name: 'home',
  components: {
    Hello
  }
}
</script>

NOTE: In template, you can refer to the component via kebab-case (component-name) or PascalCase (ComponentName).

Receiving data in Child

<template>
  <div>
    Hello {{ item.name }}
  </div>
</template>

<script>
export default {
  props: ['item']
}
</script>

Click event / Methods

<template>
  <div>
    <button @click="increment">{{ count }}</button>
    <a href="#" @click.prevent="increment">{{ count }}</a>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count += 1
    }
  }
}
</script>

NOTE: @ is shorthand fpr v-on:

NOTE: .prevent modifier tells the v-on directive to call event.preventDefault() on the triggered event

Bind attributes

<template>
  <div>
    <a :href="url">Google</a>
    <a :href="url + '?q=' + q">Query</a>
    <a :href="buildUrl()">Build Query</a>
  </div>
</template>

<script>
export default {
  props: ['item'],
  data() {
    return {
      url: 'https://www.google.com/search',
      q: 'hello'
    }
  },
  methods: {
    buildUrl() {
      return `${this.url}?q=${this.q}`
    }
  }
}
</script>

NOTE: : is shorhand for v-bind:

v-model for input

<template>
  <div>
    <input v-model="nickName" placeholder="Nick name">
    Hi {{ nickName }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      nickName: ''
    }
  },
}
</script>

Computed

<template>
  <div>
    Hello {{ item.name }} ({{ nameUpper }})
  </div>
</template>

<script>

export default {
  props: ['item'],
  computed: {
    nameUpper() {
      return this.item.name.toUpperCase()
    }
  }
}
</script>

NOTE: Computed properties are cached based on their reactive dependencies. You could achieve the same via methods without the benefit of caching.

NOTE: Computed vs Watched Property

NOTE: Computed Setter

NOTE: Watchers

Communication

Parent call Child method

Child notify Parent

Others

References:

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.