My Singular Vue Reference

How-To Reference

The deeper I get into learning Vue, the more notes I have to take 😄 I’m getting a bit annoyed with combing through my separate Vue posts to find information, so I’ll condense everything here instead. This post will be a straight copy-paste job from some of my previous posts, and I’ll add new information in the future as I learn it.

Table of Contents

My Favorite Vue Resources

These are the websites and repos that have taught me Vue.

Official Docs

My Vue Learning Repos

Video Courses I Found To Be Very Helpful

Useful Blog Posts On Various Topics

Vue + TypeScript

  • Here’s a video intro’ing TypeScript particularly with Vue (note: it demos using Classes in Vue, which has been phased out).
  • This series is a tutorial similar to Traversy’s above, but implementing TypeScript
  • This video demonstrates a basic Vue app, comparing the vanilla JS way, the Class way, and the TypeScript way

Courses I May Find Useful In The Future

Installing Vue & Vue UI

To install Vue:

npm install -g @vue/cli

The main tutorial I’m doing this with showed a cool demo of Vue UI so I thought I’d try it out. So next step to create the actual Vue app is to invoke it:

vue ui

Creating A Vue Project

…and then create a new project. This walks you through a bunch of steps; I did:

  • named the client app ‘client’ making sure I’m in the app’s parent folder
  • selected npm as my package manager (it’s the default I later learned…not necessary to change)
  • unticked the option to create a git repo…it’s already in a git repo
  • chose a manual preset in order to be able to add TypeScript
  • added TypeScript as an enabled feature
  • unticked the option to use class-style component syntax
  • chose which ESLint option to install (‘error prevention only’ to go the minimal style, but whatever option is comfortable is fine)
  • Create Project!

It took a while to install, but created the app in the end. Then you can run it from the UI in the Tasks tab, and clicking serve then Run task. Otherwise run npm run serve (assuming npm) from the command line in the client directory.

For the first time it will take a little while for the build to complete, but when it does you can visit the app at localhost:8080 (or just click the **Open app button in the CLI). Also not a bad idea to git commit the installation here before making any customizations.

A few initial things I noticed using the UI tool…

  • To see the console output (including any runtime errors), open Tasks –> Output

Plugins and utilities like Vuetify, Vue Router, and Vuex can be added from the Vue GUI:

  • Go to the Plugins tab
  • Click ‘add plugin’
  • Search for *vuetify (or whatever plugin) and then click vue-cli-plugin-vuetify when it comes up, and install it
  • Leave the default preset and the click Finish installation and let it do its installation magic

Basic Component Structure

Every Vue component is made up of three basic building blocks:

  • <template></template> — Vue-ified HTML of how the component should actually be structured
  • <script></script> — import utilities and export data, methods, etc. for each component
  • <style></style> — style the bad boy

One important thing to note about the style element: adding the scoped attribute limits CSS to this component only:

<style scoped>
h3 { margin: 40px 0 0; }

Passing Props

The simple way to register props that have been passed down to a component is to list them in an array:

export default {
props: ['length', 'image'],

This is acceptable, but best practice says it’s better to be more specific about prop types, defaults, and requirements to reduce bugs, errors, omitted props, etc. You can also add validators to further defend against human error.

export default {
props: {
length: {
type: [Number, String], // allows for either type to be accepted
required: true,
image: {
type: String,
default: '/images/placeholder.png',
// required isn't necessary since there's a default
validator: propValue => {
// require image to be in a specific directory
const hasImagesDirectory = propValue.indexOf('/images/') > -1;
// require file to be valid file type
const isPNG = propValue.endsWith('.png');
const isJPEG = propValue.endsWith('.jpeg') || propValue.endsWith('.jpg');
const hasValidExtension = isPNG || isJPEG;

return hasImagesDirectory && hasValidExtension;

The accepted prop types are the basic JavaScript data types: String, Number, Boolean, Array, Object, Date, Function, and Symbol.

Form Input Binding

One important thing to know: v-model overwrites the value attribute on text elements, so it’s not necessary to include.

Note: This is not true for checkboxes or radios, you still need the value there.

I was used to doing this out of habit, and also Emmet auto-complete…must remember to remove this attribute when creating forms!

The same is true for adding the checked or selected attributes to checkboxes and selects. See docs.

By the way, I guess you don’t need the name element either? Since it’s used to organize data going to the serve, but with Vue the data model handles that instead.

.lazy Modifier is Great! Replaces Debouncing

In React (from what I know) it’s a complicated process to debounce user input, i.e. stop the form from acting on the input with every key press. Vue has this cool .lazy modifier which means it won’t react to the input data until focus changes away from the input. Example:

<label for="title">Title</label>
<input type="text" v-model.lazy="blog.title" id="title" required />

Vue Router - How Routing Works in History Mode

Normally when a URL has a slash in it, or a path, it sends a request to the server:

Vue by default allows for routing in “hash mode”…the hash is used to prevent the browser from making a new server request:

But this is lame! So instead vue-router needs to be set up in history mode so that no matter the path, the index.html file will be loaded. See docs.

One important thing to note—history-mode routing works by default in development mode when running npm run serve, but in production there is some extra configuration to do depending on the production setup.


Vuex is a state manager that sits across an entire application (similar to Redux in React world). I watched the NetNinja’s Vuex tutorial playlist to get acquainted with it.

This article is a good example of using Vuex to implement a global flash alert, aka snackbar.


Vuetify is a component library which implements the Material Design principles for Vue apps. One thing I saw that I might like to try is implementing a dark theme toggle. You can do this by adding a button control in App.vue which calls a method:

<v-btn @click="toggleTheme">Toggle Theme</v-btn>

The method is simple too:

export default {
name: 'App',
methods: {
toggleTheme() {
this.$vuetify.theme.dark = !this.$vuetify.theme.dark

Here are the docs to see which properties can be customized in a theme.

Vetur & Formatting

Vetur is a VS Code plugin that takes care of syntax highlighting and formatting in Vue files. It did one really annoying thing that always bothered me and I finally figured out how to fix it.

Vetur uses prettier-html as the default formatter for the <template> sections of Vue files, and this formatter by default wraps element attributes so they look like this:

class="red white--text"
>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eaque totam corrupti sint veritatis. Voluptas, reprehenderit culpa porro, molestias perspiciatis possimus recusandae!</p>
class="pink lighten-4 red--text text--darken-4"
>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eaque totam corrupti sint veritatis. Voluptas, reprehenderit culpa porro, molestias perspiciatis possimus recusandae!</p>

I hate this.

It took a while to figure out what was actually doing this (Vuetify? ESLint? Some other VS Code setting?) but finally this article illuminated everything. Long story short the solution was to change the Vetur formatter for HTML from prettier-html to js-beautify-html and then to tell it not to wrap attributes.

In learning that Vetur was injecting Prettier formatting into the files, I was also able to adjust some other things that had been niggling, though not so strongly. The final settings I added to my VS Code settings.json were:

"vetur.format.defaultFormatter.html": "js-beautify-html",
"vetur.format.defaultFormatterOptions": {
"js-beautify-html": {
"wrap_attributes": "auto"
"prettier": {
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "avoid"

Problem solved!