DOBROMIR HRISTOV
We will build a simple multi page Vue SPA in the form of a dynamic map of Westeros from Game of Thrones.
The map will be populated by the 9 great houses, each in its respective place.
Each house will have a drop down menu with a few of its main members.
Each member will have their own personal page.
....
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
</head>
<body>
  <div id="app">
    {{ vueText }}
  </div>
<script>
var app = new Vue({
  el: '#app',
  data: {
    vueText: 'Hello Vue'
  }
})
</script>
</body>
</html><div id="app">
    Hello Vue
</div><div id="app">
  <div>
    {{ vueText }}
  </div>
  <input type="text" v-model="vueText">
</div><div v-if="isVisible === true"> That's hot! </div>Expression Body
Directive Name
<div v-if="false">
    Invisible div?
</div><div v-show="false">
    Invisible div?
</div><!----><div style="display: none">
    Invisible div?
</div>Conditionally display elements in the DOM
Hides the element
Removes the element
<div class="pepper" v-for="chilli in chillies">
    {{ chilli }}
</div>// the Vue Instance
data: {
    chillies: [
      'Cayenne',
      'Habanero', 
      'Jalapeno', 
      'Ghost Pepper', 
      'Trinidad Moruga Scorpion', 
      'Carolina Reaper'
    ]
  }
Dynamically binds DOM element attributes to data on the Vue instance
<button :disabled="isSaving === true"> 
    Save Form
</button><button disabled="disabled"> 
    Save Form
</button>v-bind:property has a shorthand as just :property
data: {
  isSaving: true
}<button :disabled="isActive" :class="userEnergyLevel"> 
    Get in Shape
</button>
<div :class="{ active: isActive }"> Sports! </div>
<div :class="[ favoriteSport, isActive ? 'active': 'passive' ]">
    Activity
</div>
<!-- assign multiple at once -->
<div v-bind="{ class: { active: isActive }, title: 'Healthy' }">
   Running is fun.
</div><button disabled="disabled" class="low"> 
    Get in Shape
</button>
<div class="active"> Sports! </div>
<div class="rugby active">
    Activity
</div>
<!-- assign multiple at once -->
<div class="active" title="Healthy">
   Running is fun.
</div>data: {
    isActive: true,
    userEnergyLevel: 'low', 
    favoriteSport: 'rugby'
}Creates a two way bond between a form element and data property on the instance
<form>
  <label>Recipe Name</label>
  <input v-model="form.name" type="text">
  <label>Portions</label>
  <input 
    v-model="form.portions" 
    type="number">
  <label>Vegan 
    <input 
      v-model="form.isVegan" 
      type="checkbox">
  </label>
  <label>Difficulity</label>
  <input 
    v-model="form.difficulity" 
    type="range">
</form><button @click="counter++"> 
    Increment
</button><div class="vueDog vuePet" 
     @click="vueDog = !vueDog">
    <img v-if="vueDog"
         src="vueDog.jpeg">
    <div class="text"> Tap the doggy </div>
</div>
  <div class="vueReprtile vuePet" 
       @mouseenter="vueReptile = true" 
       @mouseleave="vueReptile = false">
    <img 
      v-show="vueReptile" 
      src="vueReptile.jpg">
    <div class="text"> Touch the gecko </div>
</div>
<div class="vueReprtile vuePet" 
       @mousedown="vueLeo = true" 
       @mouseup="vueLeo = false">
  <div class="text"> Keep finger on the leo </div>
  <img v-show="vueLeo" 
       src="https://image.ibb.co/cD9xMV/Vue-Leopard.jpg">
</div><input type="text" v-model="username"><input
  :value="username"
  type="text"
  @input="username = $event.target.value"
>Intelligently handles different form element components by listening and handling data in the required way
<input type="checkbox" v-model="isVisible"><input 
  :checked="isVisible" 
  type="checkbox"
  @change="isVisible = $event.target.checked"
>Expand under the hood to
Make templates easier to read and manage.
Can be used inside moustache expressions or dynamic bindings
data: {
    counter: 0
},
methods: {
   increment() {
     this.counter = this.counter + 1
   }
}<button @click="increment">Add one</button>
<div>{{ counter }}</div><button @click="increment">+1 boringness</button>
<button @click="incrementBy(10)">+10 boringness</button>
<button @click="incrementTimes(5)">x5 boringness</button>
data: {
    boringMeter: 0
},
methods: {
   increment(){
     this.incrementBy(1)
   },
   incrementBy(number = 0){
     this.boringMeter = this.boringMeter + number
   },
   incrementTimes(times = 2) {
     this.boringMeter = this.boringMeter * times
   }
}// ...
data: { 
    firstName: 'John', 
    lastName: 'Doe' 
},
computed: {
  fullName() {
    return this.firstName + ' ' + this.lastName
  }
},
<div>{{ fullName }}</div><div>John Doe</div><input v-model="search" type="text"> 
<div
  v-for="chilli in filteredChillies"
  :key="chilli"
  class="pepper" 
>
  {{ chilli }}
</div>data: {
  search: "",
  chillies: [ "Cayenne", "Habanero", ... ]
},
computed: {
  filteredChillies() {
    return this.chillies.filter(chilly => {
      return chilly
        .toLowerCase()
        .includes(this.search)
       }
    );
  }var counter = {
    template: '<button @click="increment">{{ count }}</button>',
   
    data() {
       return {
            count: 0
        } 
    },
    methods: {
        increment(){
            this.count = this.count + 1
        }
    }
}
Vue.component('VCounter', counter) // Global component registration<div>
    <v-counter></v-counter>
</div>var VCounter = {
    template: '<button @click="increment">{{ count }}</button>',
   
    data() {
       return {
            count: 0
        } 
    },
    methods: {
        increment(){
            this.count = this.count + 1
        }
    }
}
new Vue({
  el: '#app',
  components: {
    VCounter: VCounter // Local Component registration
  }
})var component = {
 data: () => ({ title: '' }),
 template: '<div class="someClass">{{title}}</div>'
}<script type="text/x-template" id="unique-id">
 <div class="someClass">
    {{ title }}
 </div>
</script>
<script>
var component = {
    data: () => ({ title: '' }),
    template: '#unique-id'
}
</script>String or template literal
X-template template tag
const component = {
  data: () => ({ title: '' }),    
  render() {
    return <div class="someClass">{ this.title }</div>
  }
})JSX
const component = {
  data: () => ({ title: '' }),
  render(createElement) {
    return createElement('div', { 
        class: ['someClass']
      }, 
      this.title)
    }
}Render Function
<counter :min="5" :step="5" :max="100"></counter>
props: ['PropA', 'PropB']
props: {
  PropA: Object,
  PropB: String
}
props: {
  PropA: { 
      type: Object, 
      required: true 
  },
  PropB: { 
      type: String, 
      default: 'Lorem Ipsum'
  }
}
Shortest - mostly for demos
Slightly Longer
Longest - recommended, most detailed
<v-counter :increment-by="5"></v-counter>{
  template: '<button @click="increment">{{ count }}</button>',
  props: {
    incrementBy: {
      type: Number,
      default: 1
    }
  },
  data() {
    return { count: 0 } 
  },
  methods: {
    increment(){
       this.count = this.count + this.incrementBy
    }
  }
}Props are considered immutable to child components.
Default value for a prop of type Object or Array should be a factory function returning the required data.
Use as kebab-case in templates, but as camelCase inside the component instance.
Way for child components to communicate with parent components.
template: '<button @click="notifyParent">click me</button>',
data: () => ({ count:0 }),
methods: {
  notifyParent() {
    this.$emit('change', this.count)
  }
}<counter @change="handleChange"/>methods: {
  handleChange(count) {
     // handle event
  }
}Parent Component
Child Component
{
  props: {
    incrementBy: {
      type: Number,
      default: 1
    },
    value: {
      type: Number,
      required: true
    }
  }, 
  methods: {
      increment(){
          const value = this.value + this.incrementBy
          this.$emit('input', value)
      }
  }
} <v-counter
    :increment-by="5"
    :value="currentCount"
    @input="handleInput"
 ></v-counter>Child Component
Parent Component
{
  data() {
    return {
      currentCount: 0
    }
  }, 
  methods: {
    handleInput(emittedValue){
      this.currentCount = emittedValue
    }
  }
}<button @click="increment">{{value}}</button>npm install -g @vue/cli
vue create my-projectvue ui<template>
  <button class="v-button" @click="inc">{{ count }}</button>
</template>
<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    inc() {  
      this.count = this.count + 1  
    }
  }
}
</script>
<style lang="scss">
.v-button {
    background: $red;
    padding: $button-padding;
}
</style>
All of the above are solved by Vue CLI out of the box.
// 1. Define some routes
const routes = [
  { path: '/', component: HomePage },
  { path: '/user/:id', name: 'users', component: UserPage, props: true }
]
// 2. Pass the routes
const router = new VueRouter({
  routes: routes
})
var app = new Vue({
  el: '#app',
  router: router
})website.com/user/:idwebsite.com/user/1<div id="app">
    <the-header></the-header>
    <div class="main-wrapper">
        <router-view></router-view>
    </div>
    <the-footer></the-footer>
</div><div id="app">
    <the-header></the-header>
    <div class="main-wrapper">
        <!-- child is injected -->
        <user-page></user-page>
        <!-- parent template continues -->
    </div>
    <the-footer></the-footer>
</div><router-link to="/about">Go to About</router-link>
<router-link :to="{ name: 'about' }">
    Go to About
</router-link>
<router-link :to="{ name: 'user', params: { id: 1 } }">
    Go to About
</router-link><a href="/about">Go to About</a>
<a href="/about">Go to About</a>
<a href="/user/1">Go to User 1</a>
Define a component called WesterosMapPage that will represent the home page.
Copy App.vue's logic and template to the component.
Assign it as home with / path on the router.