Eric The Coder
Eric The Coder Blog

Eric The Coder Blog

Ultimate Vue.js (2021) Cheat Sheet

Ultimate Vue.js (2021) Cheat Sheet

Most VueJS concepts including VueRouter, Vuex and Composition API

Eric The Coder's photo
Eric The Coder

Published on Aug 12, 2021

18 min read

If you want more content like this one, click Follow and follow me on twitter @EricTheCoder_

I put a lot of hours creating this cheat sheet, I hope you will like it!

If you discover any errors or have any suggestions please leave a comment at the bottom of this page.

Must have VSCode extensions for VueJS

Addition to VSCode settings.json

emmet.includeLanguages: {
    'vue' : 'html',
    'vue-html': 'html'
}

How to install VueJS

Vue is a progressive framework. You can use it just in a small part of your web page or if you prefer you can use the Vue CLI tool to scaffold a full VueJS application.

Use Vue only on part of your web page

  • Add a 'script' tag that contains a link to the VueJS CDN library
  • Add another 'script' tag that contains a link to your Vue application file (app.js)
  • Create a div with id = "app" which will serve as a container for rendering your Vue application.

Here is an example of a page using Vue.js
(index.html)

<html>
  <head>
    <title>Ma page Vue.js</title>
  </head>
  <body>
    <div id="app">
      {{ title }}
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="./app.js"></script>
  </boby>
</html>

(app.js)

// function to initialize Vue.js instance
Vue.createApp({
    data() {
        return {
            title: "Hello Word Vue"
        }
    }
}).mount('#app') 
// .mount specifies that the Vue application will be render in the div with id = "app"

Create a full VueJS app

The tool for creating a VueJS project is Vue CLI. You will need to install it

npm install -g @vue/cli

Create your VueJS app

vue create my-app-name

npm run serve

Once the application is created, you can position yourself in the folder and start the development server

cd my-app-name
npm run serve

Vue add

It is possible to add plugins / libraries to your Vue project using the 'vue add' shortcut. Here are 3 examples:

vue add vue-router
vue add vuex
vue add tailwind

Entry point

Vue CLI will create multiple folders and files. The starting point is public / index.html and "src / main.js"

import { createApp } from "vue";
import App from "./App.vue";

createApp(App).mount("#app");

The component which serves as an entry point is therefore App.vue

With a Vue application, no HTML code will be written to the index.html file. Your HTML code will be written in the <template> section of each of your components

Single-File Component

Each Vue component is defined in its own .vue file with the following syntax <template> <script> <style>

<template>
    <img alt="Vue logo" src="./assets/logo.png" />
    <HelloWorld msg="Hello Vue 3" />
    {{ message }}
</template>

<script>
    import HelloWorld from './components/HelloWorld.vue'

    export default {
        components: {
            HelloWorld
        },
        data() {
             return {
                message: 'Hello World'
            }
        },    
    }
</script>

<style scope >
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      text-align: center;
      color: #2c3e50;
    }
</style>

Use a component inside your current component.

<template>
    <HelloWorld msg="Hello Vue" />
</template>

You then need to import the component file:

import HelloWorld from './components/HelloWorld.vue'

Component Props

Components can can define and pass a props value when rendering

The props is define inside your component with this syntax

props: {
    title: {
        type: String,
        required: true,
        default: 'Mon application'
    }
},

Props can also be used with shorthand syntax

props: ['title'],

You can then assign a value to these props when using the component

<div>
    <nav-bar title="My App" />
</div>

Component file location

Single-File-Component are saved in the src / components or src / pages folder depending on whether the component acts as a page (eg About.vue) or as a reusable component (eg NavBar.vue)

Component Data()

The data () function is used to create reactive variables that will be used in your Vue application. Whenever a reactive variable is changed, whether it is displayed or used in your page, Vue will update it immediately.

To display a reactive variable or an expression in your page you must use the double brackets Vue will replace the content of the expression with its value

// variable
{{ title }}

// expression
{{ title.toUpperCase() }}

VueJS directives

VueJS directives are html attributes that can be inserted into your page in order to modify the rendering of your Vue application.

Here is the list of available directives:

v-bind

Allows you to assign an expression to an attribute. Vue will replace the expression with its value

(eg image_url: "example.com/car.jpg"

<img v-bind:src="image_url" />

// ou syntaxe raccourci
<img :src="image_url" />

v-once

With the v-once directive Vue will interpolate the expression only once. The expression will therefore be ignored for all other refreshes

<div v-once>
   {{ title }}
</div>

v-html

Allows you to display an expression with HTML tags.

ex: title: "<h1>Hello World</h1>"

<div v-html="title">
</div>

v-model

Used to link the value of an input element with a variable. If you change one or the other Vue will automatically update the other. As a result, the variable and the input element will always have the same value.

<input v-model="name" type="text" />
<div>
    Nom : {{ name }}
</div>

v-if, v-else-if et v-else

Makes an element visible or not visible depending on the true or false value of the expression. When not visible, the element is not rendered in the html

<div v-if="amount > 100">
    Free Shipping!
<div>
<div v-else-if="montant > 50">
    Shipping: 9.95$
</div>
<div v-else>
    Shipping: 19.95$
</div>

v-show

Makes an element visible or not visible depending on the true or false value of the expression. The element always remains present in the rendering. When not visible the element is rendered with the CSS attribute: display: none;

<div v-show="isError">
  {{ errorMessage }}
</div>

v-for

Display a list of items

<ul>
    <li v-for="item in items" :key="item.id">
        {{ item.name }}
    </li>
</ul>

Note the attribute "key" is necessary to allow Vue to uniquely identify the element

Ref

Allows your Vue application to identify an html element and perform actions on that element.

<input type="text" ref="name">

Manipulation from your Vue code using the special object: this.$refs

methods: {
  handleClick() {
    console.log(this.$refs.name)
    this.$refs.name.classList.add('active')
    this.$refs.name.focus()
  }
}

v-bind on the "class" attribute and the "style"

It is possible to v-bind the class and style attributes

<div class="text-2xl" :class="isAdmin ? 'text-red-500' : 'text-gray-500'">
   Hello World
</div>

Note that the class attribute is used twice. Vue will combine these two attributes on render

It is also possible to use an object to send content in our "class" attribute

<div :class="{ 'text-red-500': isAdmin, 'text-gray-500': !isAdmin }">
   Hello World
</div>

Note the syntax of the object {attribute: expression} if the expression returns true then the attribute will be added to the class

Similar syntax applies to the style attribute

<div :style="{'margin-top': '10px', 'padding': '5px'">
   Hello World
</div>

Finally the class and style attributes can be defined by an object type variable created elsewhere in your application

titleClass: {
    'text-red-400': this.isAdmin,
    'text-gray-500': !this.isAdmin
}
<div :class="titleClass">
   Hello World
</div>

<template> tag

This element allows you to use Vue directives without creating an html element.

<template v-show="quantity === 0">
    Quantity must be greater than zero
</template>

Events

Vue allows you to manage javascript events like click, input, change, etc. To do this you must use the v-on: directive followed by the name of the event.

v-on:click

Allows you to execute code on the click of an element

<button v-on:click="name = 'Mike'">Display a message</button>

// or shortened syntax
<button @click="name = 'Mike'">Display a mssagee</button>

v-on:keydown

Allows you to execute code at the press of a key (e.g. enter)

<button v-on:keydown.enter="name = 'Mike'">Display a message</button>

// or shortened syntax
<button @click="name = 'Mike'">Display a message</button>

Other possible values for v-on: keydown, keyup, keypress

Other possible values for .enter, tab, esc, up, down, left, right, delete

v-on:submit

Allows you to run code when submitting a form

<form v-on:submit.prevent="name = 'Mike'">
    <input v-model="name" type="text" /> 
    <button type="submit">Save</button>
</form>

Note the presence of ".prevent" after the v-on: submit directive. This instruction will prevent the form from being submitted to the server.

Methods

Vue js allows you to create methods in order to place a reusable code block in your applications. Here is the syntax for creating a method:

Vue.createApp({
    data() {
        return {
            name: "Mike Taylor",
        }
    },
    methods: {
        resetName() {
            this.name = ''
        }
    }
}).mount('#app')

Note the keyword 'this' placed in front of the name variable. This keyword is mandatory to allow to reference a variable inside our Vue instance.

To call a method you can do it simply by using its name.

<input v-model="name" type="text" /> 
<button @click="resetName" type="text">Delete</button>

A method can also contain parameters

methods: {
    resetName(newName) {
        this.name = newName
    }
 }
<input v-model="name" type="text" /> 
<button @click="resetName('John')" type="text">Effacer</button>

A method can also send the object event

methods: {
    resetName(newName, e) {
        this.name = newName
        console.log(e.target.textContent)
    }
 }
<input v-model="name" type="text" /> 
<button @click="resetName('John', $event)" type="text">Delete</button>

Note the special parameter $event will send the object event to our method

$emit

The keyword $emit is used to emit an event. This event can then be captured by your application with a v-on: event-name

methods: {
    sendDelete() {
        const userId = 10
        this.$emit('delete', userId)
    }
}
<div>
    <nav-bar title="My App" v-on:delete="deleteUser" />
</div>

Computed Methods

Unlike the other methods which will be re-executed each time your application is rendered, the "computed" methods will be re-executed only if the variables they contain are modified.

computed: {
    recalcTotal(items, taxes) {
        return  this.calcTotal(items, taxes)
    }
}

The "computed" methods can then be called in our page.

<button @click="recalcTotal">Re-Calc</button>

Note that no parameter or parenthesis is used

Watch Method

These methods will "watch" a variable and as soon as it changes will execute the code of the method.

watch: {
    title(newTitle, oldTitle) {
        console.log(`Le titre ${oldTitle} à changé pour ${newTitle}`)
    }
}

Lifecycle Hook Methods

Each view instance goes through a series of initialization steps when it is created - for example, it needs to set up data observation, compile the template, mount the instance on the DOM, and update the DOM. when the data changes.

Along the way, it will also invoke lifecycle hooks, which give us the opportunity to execute custom logic at each step.

For example, the "created" hook is called after the instance is created

created() {
   console.log('Component instance created')
 }

There are several other hook methods. Here are a few:

beforeCreate created beforeMount mounted beforeUpdate updated beforeDestroy destroyed

Les Slots

Slots allow you to add content to a component

<custom-button>
  ...custom content...
  Titre: {{ title }}
</custom-button>

Note that the rendering of 'title' will be done in the parent component. The same principle will apply for the css. So the content of the slot must be defined / accessible in the parent component

Internally the custom-button looks something like this:

<template>
  <slot></slot>
</template>

The slot tag will be replaced by the content of 'custom-button'

It is possible to define a default value for the slot

<template>
  <slot>If nothing than display this</slot>
</template>

Note that the default value is defined in the child component, so must use the variables or the css defined in the child component.

Multiple slots

Allows you to add content associated only with a particular slot

<custom-button>
   Custom Content
  <template #title>
    {{ title }}
  </template>
</custom-button>

'#title' identifies the template in the title slot. The v-slot: title syntax can also be used

Internally the custom-button looks something like this:

<template>
  <slot></slot>
  <slot name="title"></slot>
</template>

Note that the main slot is still available

(the tags here are optional) but it is possible to add a second slot with a name

Slot Props

Slots can have props

<template>
  <slot name="title" status="info"></slot>
</template>

The Props can then be used

<custom-button>
    custom content...
  <template #title="titleProps">
    {{ title }}
    {{ titleProps.status }}
  </template>
</custom-button>

It is possible to define Props for the main slot using '#default'

<template>
    <slot type="ajout"></slot>
  <slot name="title" status="info"></slot>
</template>
<custom-button>
  <template #default="defaultProps">
       custom content...
     {{ defaultProps.type }}
  </template>
  <template #title="titleProps">
    {{ title }}
    {{ titleProps.status }}
  </template>
</custom-button>

Note that if there is no named slot. It is possible to use the default Props with this syntax

<custom-button #default="defaultProps">
       custom content...
     {{ defaultProps.type }}
</custom-button>

Vue Router

Client-Side Routing

The client-side routing allows you to change the url address of the browser and load another Vue page / component without refreshing the browser. All this is possible thanks to the VueRouter library.

Installation VueRouer v4

npm install vue-router@4

// or vue cli plugin
vue add router

VueRouter Configuration

Add in main.js

import { createApp } from 'vue'
import App from './App.vue'
import * as VueRouter from 'vue-router'
import Home from './pages/Home.vue'
import About from './pages/About.vue'

const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      component: About
    }
  ]
})

const app = createApp(App)
app.use(router).mount('#app')
app.mount('app')

RouterView

This component comes with the vue-router library and acts as a container to render the routes we have defined

App.vue

<router-view></router-view>

On clicking this element, Vue will render the route specified by the 'router-link' tag and the 'to =' attribute. The render will take place where you placed your <router-view> </router-view>

<template>
    <div>
      <h1>Home page</h1>
      <router-link to="/about">About</router-link>
    // or
      <router-link :to="{ name: About }">About</router-link>
    </div>
</template>

<script>
  export default {

  }
</script>

<style lang="scss" scoped>

</style>

Route Parameters

It is possible to extract the information relating to the path. Like for example the Id of a product: /products/id

routes: [
    ...
    ...
    {
      path: '/products/:id',
      name: 'ProductDetails',
      component: ProductDetails
    },
  ]
})

You can then launch the link from the Products component

<router-link :to="{ name: 'ProductDetails', params: { id: product.id }}">
    See details
</router-link>

It will finally be possible to read this parameter from the ProductDetail component:

<template>
    The product ID is {{ $route.params.id }}
</template>

It is also possible to read this parameter as a component Props (eg ProductDetails component)

<template>
    The product ID is {{ idid }}
</template>

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

To enable the conversion of the parameter to Props, you must mention it when you define the route.

routes: [
    ...
    ...
    {
      path: '/products/:id',
      name: 'ProductDetails',
      component: ProductDetails,
      props: true,
    },
  ]
})

$route / this.$route

Is a global object that contains information about the current route:

  • name
  • fullPath
  • path
  • query
  • params

Route redirection

It is possible to redirect from one road to another.

routes: [
    ...
    ...
    {
      path: '/about-us',
      redirect: '/about',
    },
  ]
})

Route Alias

It is possible to have two routes which display the same component

routes: [
    {
      path: '/',
      name: 'Home',
      component: Home,
      alias: '/home'
    },
  ]
})

'/' et '/home' point to the same component.

The alias property can also be an array ['/ home', '/ homepage']

404 redirect

It is possible to redirect a page if the route does not exist

routes: [
    ...
    ...
    {
      path: '/:catchAll(.*)',
      name: 'NotFound',
      component: NotFount
    },
  ]
})

Modify the route in your code with this.$router

methods: {
    redirect() {
        this.$router.push({ name: 'Home' })
    },
    back() {
      this.$router.go(-1)
      // or same thing
      this.$router.back()
    },
    forward() {
      this.$router.go(1)
      // or same thing
      this.$router.forward()
    }    
}

Route query

It is possible to read the query parameters passed to the route ex: /products?brand=Apple

<template>
    Filter Brand : {{ $route.query.brand }}
</template>

It is possible to call a route with a query parameter

methods: {
    search(brand) {
    this.$router.push({ name: 'Home', query: brand })
    },
}

If query is equal to undefined then it will not appear in the url bar of the browser

Nested Routes

Allows you to manage the sub-routes. ex: / products / 1050 / tags

You must first define the sub route with the property children

routes: [
    ...
    ...
    {
      path: '/products/:id',
      name: 'ProductDetails',
      component: ProductDetails,
      props: true,
      children: {
        path: 'tags',
        components: Tags,
      }, 
    },
  ]
})

In the ProductDetails component you can display the component tags using <route-view> tags

<template>
  Product no
  {{ $route.params.id }}

  List of tags associated with the product
  <router-view></router-view>
</template>

Composition API

Is an alternative to the Option API and allows us to write our code bundled and more naturally, without using properties / objects and without using the keyword 'this.'

setup() method

All the code of your component will be write inside this method

<template>
</template>

<script>
  export default {
    setup() {
       ..component code..
    }
  }
</script>
<style>
</style>

Note that the template and style section remains unchanged

Return value of the setup () method

If you want to use a variable or a function outside the setup () method, in the template for example, you must return it in the return () method

<template>
  {{ title }}
</template>

<script>
  export default {
    setup() {
      let title = 'My Title'

      return {
        title,
      }
    }
  }
</script>

Props

You can access your component's props with the props parameter

<script>
  export default {
    props: ['title']
    setup(props) {
      console.log(props.title)

      return {

      }
    }
  }
</script>

Reactive Variables

To use the v-model directive on a variable. you must make this variable reactive with the function ref()

<template>
  <input v-model="title">
</template>

<script>
  import { ref } from 'vue'
  export default {
    setup() {
      let title = ref('My Title')

      return {
        title,
      }
    }
  }
</script>

.value property

To modify a reactive variable, declared with ref(), you must use its .value property

<template>
  <input v-model="title">
</template>

<script>
  import { ref } from 'vue'
  export default {
    setup() {
      let title = ref('My Title')
      title.value  = 'Hello World'

      return {
        title,
      }
    }
  }
</script>

The ref directive can also be used to create a binding with an html element (replacing this.$ref in the API option))

<input :ref="title" type="text" />
<script>
import { ref } from 'vue'

export default {
  setup() {
    import { ref } from 'vue'

    const title = ref(null)

     return {
       title,
     }
  }
</script>

reactive: an alternative to the ref function

<template>
  <input v-model="state.title">
</template>

<script>
  import { reactive } from 'vue'
  export default {
    setup() {
      const state = reactive({
        title: 'My Title'
      }

      state.title  = 'Hello World'

      return {
        person,
      }
    }
  }
</script>

Note that the reactive function only takes an object as a value (no string, number, etc.) and that unlike the ref() function you should not use the .value property to return the value of the variable.

Combination of BeforeCreate and Created Lifecycle Hook

To run code when creating the component simply place some code directly in setup()

<template>
  <input v-model="title">
</template>

<script>
  import { ref } from 'vue'
  export default {
    setup() {
      let title = ref('My Title')
      title.value  = 'Default value on creation'

      return {
        title,
      }
    }
  }
</script>

onMounted

Allows you to run code when creating the component

<script>
export default {
  import { onMounted, ref } from 'vue'
  setup() {
    let products = ref(null)

    onMounted(async () => {
      const response = await fetch('https://fakestoreapi.com/products')
      products.value = await response.json() 
    })
}
</script>

Emit

The emit function replace $emit

<template>
  <button @click="save">save</button>
</template>

<script>
  import { ref } from 'vue'
  export default {
    setup(props, { emit } ) {
      const id = 12
      const save = function() {
        emit('onCLickEvent', id)
      } 
      return {
        save,
      }
    }
  }
</script>

Using the Store (Vuex)

The this.$store method is not available in composition API mode, you must now use the useStore() method

<template>
  <input v-model="title">
  <button @click="saveTitle">save</button>
</template>

<script>
  import { ref } from 'vue'
  import { useStore ] from 'vuex'

  export default {
    setup() {
      let title = ref('My Title')
      const store = useStore()

      title.value  = store.state.title

      return {
        title,
        saveTitle: () => store.commit('save')
      }
    }
  }
</script>

Note that the saveTitle function is in fact a function. Returning a function allows you not to execute the commit right away but only when calling saveTitle

The computed() methods

<script>
  import { ref, computed } from 'vue'
  import { useStore ] from 'vuex'

  export default {
    setup() {
      let title = ref('My Title')
      const store = useStore()

      title.value  = store.state.title

      return {
          title,
        count: computed(() => store.state.count)
      }
    }
  }
</script>

The computed variable 'count' will be refreshed only if the value of the 'state.count' changes.

Watch method

Allows you to run code when modifying a variable

<script>
  import { ref, watch } from 'vue'
  import { useStore ] from 'vuex'

  export default {
    setup() {
      let title = ref('My Title')
      const store = useStore()

      watch(title, (new, old) => {
        console.log('The title have change')
      }

      return {
        title,
        count: computed(() => store.state.count)
      }
    }
  }
</script>

To make a watch on several variables at the same time you can use the function watchEffect ()

watchEffect(() => {
  console.log(count, title)
}

The function will run on each modification of all the variables present in the watchEffect()

Using Router and Route

In Composition API mode you cannot use 'this.$router' and 'this.$route', you will have to use useRouter and useRoute

<script>
  import { useRouter, useRoute) from 'vue-router'

  export default {
    setup() {
      const router = useRouter()
      const route = useRoute()

      router.push({ name: 'Home' })

      console.log(route.path, route.params)

    }
  }
</script>

<script setup>

It is possible to use the abbreviated syntax to create the code of your API composition

<script setup>
  import { ref, watch } from 'vue'
  import { useStore ] from 'vuex'

  let title = ref('My Title')
  const store = useStore()

  watch(title, (new, old) => {
    console.log('The title have change')
  }
</script>

Note the 'script setup' attribute allows not to use a setup() method and no return either. They are managed automatically. Vue returns with all the variables and functions defined in the top level.

Props and emit with setup attribute

<script setup">
  import{ defineProps, defineEmit, useContext } from 'vue'

  defineProps(['msg']);
  // or
  defineProps({
    title: String,
  })
  // or
  const props = defineProps({
    title: String,
  })
  // console.log(props.title)

  const emit = defineEmit(['handleClick'])
  const { slot, attrs } = useContext()
</script>

Style v-bind

With Vue 3.2, It is now possible to use v-bind within the style section

<script setup>
  import { ref } from 'vue'
  let color = ref('red')
</script>

<style scope>
```css
.title {
  color: v-bind(color);
}
</style>

Conclusion

Thank you for reading this article. If you want more content like this, click Follow or

Did you find this article valuable?

Support Eric The Coder by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
 
Share this