vueschool.io         @vueschool_io

Daniel Kelly

Teacher @ Vue School

Full Stack developer (10 years)

Husband and Father

@danielkelly_io

@danielkellyio

Alabama, USA

Rolf Haug

Teacher @ Vue School 

Vue.js Community Partner

Vue.js Oslo meetups organizer

Full Stack developer & Consultant

Foodie 🌶

Oslo, Norway

Vue.js

Est. 2014

Evan You

Creator of Vue.js

Curious of how Angular worked

🤔

👷‍♂️

Tried to build it from scratch

Made something interesting

🤓

Vue.js version 0

was born

👼

Used by a ton of companies

🏋️‍♂️

a ton

+ Many more

Impressive growth

npmtrends.com/vue

Developers are passionate about Vue

React 199k

Vue 201k

Vue is Easy to Use and Learn

Vue is Easy to Use and Learn

Vue.js

Vue is Easy to Use and Learn

React

Vue is Easy to Use and Learn

Vue is Good!

  • Lightweight (16kb min+gzip)
  • Supports tree-shaking
  • Performant
  • Scalable

Vue is progressive and easy to adopt

Can be used with any static page

Like jQuery

Can be used to build sophisticated apps

  • Single Page Applications

  • PWA's

  • Mobile apps

Vue.js Ecosystem

  • Vue Router
  • Pinia or Vuex
  • Vite or Vue CLI
  • Vue Devtools
  • Vue i18n
  • Vitest/Vue Test utils
  • Vue Server Renderer/Nuxt
  • and more!

Get Started with Vue.js

Vue can be used in any HTML page

Install Vue.js

<!-- hello.html -->
<html>
<body>
  <script src="https://unpkg.com/vue@3"></script>
</body>
</html>

Content Delivery Network

Install Vue.js

<!-- hello.html -->
<html>
<body>
  <script src="https://unpkg.com/vue@3"></script>
  <script>
    // we can use Vue in here
  </script>
</body>
</html>

Let's create a Vue Application Instance

The Vue Instance

<script>
  Vue.createApp({})
</script>

In order to use Vue in HTML we have to mount it to the DOM

Mount it to the DOM

<script src="https://unpkg.com/vue@next"></script>

<div id="app"></div>

<script>
  Vue.createApp({}).mount('#app')
</script>

Mount it to the DOM

⚡️ Vue Super Powers

<div id="app"></div>

<script>
  Vue.createApp({}).mount('#app')
</script>

Declarative Rendering

⚡️

A Vue Application

<div id="app">
  {{message}}
</div>

<script>
  Vue.createApp({
    data() {
      return {
        message: 'Hello Vueschool'
      }
    }
  }).mount('#app')
</script>

Options API

<script>
  Vue.createApp({
    data() {
      return {
        message: 'Hello Vueschool'
      }
    }
  }).mount('#app')
</script>

Data definition

Must be a function

Must return a data object

Reactivity System

⚡️

👱‍♀️User Input

A Vue Application

<div id="app">
  {{message}}
  <input v-model="message">
</div>

<script>
  Vue.createApp({
    data() {
      return {
        message: 'Hello Vueschool'
      }
    }
  }).mount('#app')
</script>

v-model directive

Two-way data binding

👏

How would you do that with Vanilla JavaScript or jQuery?

Reactivity without Vue

  1. Assign an id to the input
  2. Create an event listener to listen for the keyup event
  3. Get the value from input and set it to the text you want to update

in every place you want to display the message

Vue.js Benefits

  • Faster development and prototyping
  • Fewer chances of bugs
  • Easier and faster to refactor

Questions?

👩‍💻👨🏽‍💻 Assignment 1 (15 mins)

  • create an .html file and add Vue.js from a CDN
  • create a vue instance
  • add a data property name and bind it to an input
  • display a heading saying Hi and the given name

 

The heading should change instantly whenever the user changes the name →

👩‍💻👨🏽‍💻 Assignment 1 (15 mins)

Directives

⚡️

Directives

Special HTML attributes provided by Vue

Directives

Always start with a v-

<div id="app">
  {{message}}
  <input v-model="message">
</div>

Directives

Applies reactive behavior  to the DOM

v-bind allows us to bind Vue.js data to any HTML attribute

Common Directives

Common Directives: v-bind

<div id="app">
  <img v-bind:src="image.path" v-bind:alt="image.alt" />
</div>

<script>
  Vue.createApp({
    data() {
      return {
        image: {
          path: '/path/to/image.jpg',
          alt: 'Alternative text for an image'
        }
      }
    }
  }).mount('#app')
</script>
<div id="app">
    <img src="/path/to/image.jpg" alt="Alternative text for an image" />
</div>

Rendered Output

Common Directives: v-bind

<div id="app">
  <a v-bind:href="link.href">{{ link.text }}</a>
</div>

<script>
  Vue.createApp({
    data() {
      return {
        link: {
          href: 'https://amazon.com',
          text: 'Amazon'
        }
      }
    }
  }).mount('#app')
</script>
<div id="app">
    <a href="https://amazon.com">Amazon</a>
</div>

v-bind shorthand :

<div id="app">
    <img v-bind:src="image.path" v-bind:alt="image.alt" />
  
    <img :src="image.path" :alt="image.alt" />
</div>
<div id="app">
    <!-- Rendered output -->
    <img src="/path/to/image.jpg" alt="Alternative text for an image" />
</div>

Conditional Rendering

v-if allows us to conditionally render elements

Common Directives

Common Directives: v-if

<div id="app">
  <p v-if="sunny">
    It's sunny today! 🌞
  </p>
</div>

<script>
  Vue.createApp({
    data() {
      return {
        sunny: true
      }
    }
  }).mount('#app')
</script>

v-else-if and v-else 

Common Directives

<div id="app">
  <p v-if="sunny">It's sunny today! 🌞</p>

  <p v-else>Is it raining? ☔️</p>
</div>

<script>
  Vue.createApp({
    data() {
      return {
        sunny: true
      }
    }
  }).mount('#app')
</script>

Common Directives: v-else

Common Directives: v-else-if

<div id="app">
  <p v-if="sunny">It's sunny today! 🌞</p>

  <p v-else-if="windy">It's windy today! 🌬</p>

  <p v-else>Is it raining? ☔️</p>
</div>

<script>
  Vue.createApp({
    data() {
      return {
        sunny: false,
        windy: true
      }
    }
  }).mount('#app')
</script>

Directives support inline expressions

<div id="app">
  <p v-if="weather === 'sunny'">It's sunny today! 🌞</p>

  <p v-else-if="weather === 'windy'">It's windy today! 🌬</p>

  <p v-else>Is it raining? ☔️</p>
</div>

<script>
  Vue.createApp({
    data() {
      return {
        weather: 'hurricane'
      }
    }
  }).mount('#app')
</script>

Directives: Inline expressions

Don't bloat your template with inline expressions

Keep it simple or extract the logic

Questions?

1. add a data property animal

In the template:

2. Display a paragraph that says Dog goes woof! if the animal is a dog

3. Display a paragraph that says Cat goes meow! if the animal is a cat

4. Display a paragraph that says What does the {{animal}} say? for any other animal

 

⚠️Only one paragraph should be rendered in the browser.

👩‍💻👨🏽‍💻 Assignment 1 (10 mins)

Break? (10 min)

☕️

List Rendering

<script>
  Vue.createApp({
    data() {
      return {
        users: [
          {id: 1, name: 'Bruce Wayne', alterEgo: 'Batman'},
          {id: 2, name: 'Clark Kent', alterEgo: 'Superman'},
          {id: 3, name: 'Tony Stark', alterEgo: 'Ironman'},
          {id: 4, name: 'Diana Prince', alterEgo: 'Wonder Woman'}
        ]
      }
    }
  }).mount('#app')
</script>

We often work with arrays

v-for allows us to render lists in the DOM

Common Directives

<div v-for="something in someArray">
  <!-- something is available here -->
</div>

Can be any name

Name of the data property

Will always be an item of the array

v-for syntax

<div id="app">
  <ul>
    <li v-for="food in favoriteFood">{{ food }}</li>
  </ul>
</div>


<script>
  Vue.createApp({
    data() {
      return {
        favoriteFood: [
          'Pizza',
          'Burger',
          'Hummus'
        ]
      }
    }
  }).mount('#app')
</script>

v-for example

<div>
  <ul>
    <li>Pizza</li>
    <li>Burger</li>
    <li>Hummus</li>
  </ul>
</div>
<div v-for="user in users">
  {{ user.name }}
</div>

v-for scope

The item is available inside the element

v-for scope

The item is available inside child elements 

<div v-for="user in users">
  {{ user.name}}
  <span class="pull-right">{{ user.alterEgo }}</span>
</div>
<img 
  v-for="image in myImages" 
  :src="image.src"
  :alt="image.title" />

v-for scope

The item is available on the element

Assign a :key

When you want to reuse or reorder existing elements

So Vue can track each node’s identity

<div id="app">
  <table>
    <tr v-for="user in users" :key="user.id">
      <td>{{ user.id }}</td>
      <td>{{ user.name }}</td>
    </tr>
  </table>
</div>

<script>
  Vue.createApp({
    data() {
      return {
        users: [
          { id: 1, name: 'Huey' },
          { id: 2, name: 'Dewey' },
          { id: 3, name: 'Louie'},
        ]
      }
    }
  }).mount('#app')
</script>

:key example

  • Must be a unique identifier

  • Should not be the index of the given element in the array

v-for key

Questions?

1. Create a data property with this users array:

2. Render a div for each user

3. Within, display the user name in an h2 and create a bulleted list for user's hobbies

👩‍💻👨🏽‍💻 Assignment 1 (15 mins)

bit.ly/2zLu5Px

Interactivity

Vue.js allows us to easily to attach event listeners in our HTML

v-on allows us to add event listeners to the DOM

Common Directives

<button v-on:click="raining = true">Make it rain!</button>

Event

Handler

v-on syntax

<button v-on:click="raining = true">Make it rain!</button>

Inline handler

v-on syntax

<button v-on:click="makeItRain">Make it rain!</button>

Extracted to a method

v-on syntax

Methods

<div id="app">
  <button v-on:click="makeItRain">Make it rain!</button>
</div>

<script>
  Vue.createApp({
    data() {
      return {
          raining: false
        }
      },
    methods: {
      makeItRain () {
        this.raining = true
      }
    }
  }).mount('#app')
</script>

Methods are defined on the Vue instance

  • In the template

  • Inside other methods

Methods can be used

<script>
  Vue.createApp({
    data() {
      return {
        raining: false
      }
    },
    methods: {
      makeItRain () {
        this.raining = true
      },
      makeItRainAndSayHi () {
        this.makeItRain()
        alert('How you doing?')
      }
    }
  }).mount('#app')
</script>

We can access the entire Vue application instance under this

<button @click="makeItRain">Make it rain!</button>
<button v-on:click="makeItRain">Make it rain!</button>

v-on shorthand @

Instead of

We can listen for all native HTML events with v-on

Common HTML events

  • focus

  • blur

  • change

  • scroll

  • drag/drop

  • click

  • submit

  • input

  • mouseover

  • keyup/keydown

+++

Event Modifiers

 A shortcut for altering how browser reacts to specific events

Event Modifiers

<form @submit.prevent="submitForm">
  ...
</form>

Event Modifier Example

submitForm(event) {
  event.preventDefault()
  // ...
}

By moving the modifier to the template we keep our methods clean

Source vuejs.org

<!-- the click event's propagation will be stopped -->
<a v-on:click.stop="doThis"></a>

<!-- the submit event will no longer reload the page -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- modifiers can be chained -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- just the modifier -->
<form v-on:submit.prevent></form>

<!-- only trigger handler if event.target is the element itself -->
<!-- i.e. not from a child element -->
<div v-on:click.self="doThat">...</div>

Available event modifiers

  • .stop
  • .prevent
  • .once
  • .passive
  • .capture
  • .self

Key Modifiers

Allows us to quickly attach listeners to specific keys

Key Modifiers

<textarea @keydown.esc="clearText" />

Key Modifier Example

Available key modifiers

  • .up
  • .down
  • .left
  • .right
  • .esc
  • .enter
  • .space
  • .tab
  • .delete

Questions?

1. create a list of candidates, where each candidate has a name and a votes property

2. display each candidate’s name and votes

3. add a vote button for each candidate that will increase the candidate’s votes by 1 when clicked - using a method

 

sample list of candidates: https://goo.gl/TxHR86 →

👩‍💻👨🏽‍💻 Assignment 1 (15 mins)

👩‍💻👨🏽‍💻 Assignment 1

1. create a form using the HTML form element that adds a candidate to the list using a method.

 

Form fields: name, initial votes.

 

💡You will need to prevent default behavior.

👩‍💻👨🏽‍💻 Assignment 2 (10 mins)

  • when the escape key is hit reset all votes back to 0

 

 The root element needs to be focused 
(for example a vote button is clicked)

👩‍💻👨🏽‍💻 Assignment 3 (bonus)

💡

Directives

Clarifications and tips

Use any key
as a modifier

Tip #1

<div @keyup.l="likeImage(image)">
  <img src="img.src" />
</div>
<div @keyup.fl="performAnAction">
  ...
</div>

Create custom directives

Tip #2

<div v-click-outside="closeDropdown">
  // ...
</div>

v-click-outside

A custom directive

<!-- Dropdown example with multiple directives -->
<div v-click-outside="closeDropdown">
  
  <ul v-if="showDropdown" class="dropdown-menu" >
    <!-- dropdown items goes here -->    
  </ul>
  
  <button v-else @click="openDropdown">Menu</button>
  
</div>

Dropdown example

<!-- Dropdown example with multiple directives -->
<div v-click-outside="closeDropdown">
  
  <ul v-if="showDropdown" class="dropdown-menu" >
    <!-- dropdown items goes here -->    
  </ul>
  
  <button v-else @click="openDropdown">Menu</button>
  
</div>

Directives syntax recap

Directive

Argument

Value

<!-- Dropdown example with multiple directives -->
<div v-click-outside="closeDropdown">
  
  <ul v-if="showDropdown" class="dropdown-menu" >
    <!-- dropdown items goes here -->    
  </ul>
  
  <button v-else @click="openDropdown">Menu</button>
  
</div>

Directives syntax recap

Directive
(no argument or value)

<!-- Dropdown example with multiple directives -->
<div v-click-outside="closeDropdown">
  
  <ul v-if="showDropdown" class="dropdown-menu" >
    <!-- dropdown items goes here -->    
  </ul>
  
  <button v-else @click="openDropdown">Menu</button>
  
</div>

Directives syntax recap

Directive
(no argument)

Value

Questions?

Break (10 min)

☕️

1. Vue.js Fundamentals Workshop (Get Started with Vue)

By Alex Kyriakidis

1. Vue.js Fundamentals Workshop (Get Started with Vue)

  • 1,495