vueschool.io

@vueschool_io

Alex

Kyriakidis

Author of The Majesty of Vue.js 1 & 2

Founder & Teacher @ Vue School

Enterprise Consultant

Vue.js Contributor

Amsterdam

#1 Learning Resource for Vue.js

Our goal

280+ Video Lessons

60000 users

Alex Kyriakidis

Rolf Haug

Debbie O'Brien

Chris Fritz

Maria Lamardo

Roman Kuba

Sébastien Chopin

Filip Rakowski

Alexander Lichter

Lydia Hallie

Workshops

Vue 3 and the Composition API

Vue.js

Vue is Young and Famous

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 (20KB min+gzip)
  • Performant
  • Scalable

Vue is Options based

Vue is Options based

new Vue({
  data: {
    loading: false,
    count: 0,
    user: {}
  },
  computed: {
    double () { return this.count * 2 },
    fullname () {/* ... */}
  },
  methods: {
    increment () { this.count++ },
    fetchUser () {/* ... */}
  }
})

Vue 3

Vue 3

🐜 smaller + 🏃‍♀️ faster

📐 improved TypeScript support

🏛 more maintainable codebase

🧱 exposes lower level APIs

⭐️ new features

Vue 3

📅 coming In a few Months

🤙 most user code remains the same

🏷 pre-alpha

Vue 3

🧱 Composition API

🧱 Composition API

🆕 advanced feature

🚑 options API is not being deprecated

➕ addition to the current API

(Pre Alpha - RFC Status)

🧱 Composition API

a set of lower level APIs

use Vue features outside of Vue components

New!

🧱 Composition API

New!

import {ref, computed, watch} from 'vue'

HERE I CAN DO A LIVE EXAMPLE

New Feature in

Vue 3

the setup option

🧱 Composition API

INSIDE

Vue Components

using setup

New!

new Vue({
  beforeCreate () {

  },
  setup () {
    
  },
  created () {
	
  }
})

the setup option

New!

looks like

Lifecycle hooks

Is More Powerful Than

the setup option

New!

the setup option

New!

<template>
  <button @click="increaseCount">count {{count}} | double {{double}}</button>
</template>

<script>
  import {computed, ref} from 'vue'
  export default {
    setup () {
      const count = ref(0)
      const double = computed(() => count.value * 2)
      const increaseCount = () => {
        count.value++
      }
      return {increaseCount, count, double} // render context - unwrapped
    },
    mounted () {
      this.count = 40
      this.increaseCount()
    }
  }
</script>

the setup option

ButtonCounter.vue

New!

Already Possible

Why Composition API

♻️ Logic Reuse

🗂 Code Organization

📐 Improved TypeScript Support

🗂 Code Organisation

Organise Code By Options

  import axios from 'axios'
  import orderBy from 'lodash.orderby'
  export default {
    data () {
      return {
        characters: [],
        loadingState: null,
        orderKey: 'id'
      }
    },
    computed: {
      charactersOrdered() {
        return orderBy(this.characters, this.orderKey)
      }
    },
    methods: {
      fetchAllCharacters () {
        this.loadingState = 'loading'
        axios.get('https://rickandmortyapi.com/api/character')
          .then(response => {
            setTimeout(() => {
              this.loadingState = 'success'
              this.characters = response.data.results
            }, 1000)
          })
      },
      setOrderKey(key) {
        this.orderKey = key
      }
    },
    created () {
      this.fetchAllCharacters()
    }
  }

Fetch Resource Feature

Order Array Feature

import axios from 'axios'
  import orderBy from 'lodash.orderby'
  import {computed, ref} from '@vue/composition-api'

  export default {
    setup () {
      const characters = ref([]) // use const because you dont want to lose this value
      const loadingState = ref(null)

      const fetchAllCharacters = () => {
        loadingState.value = 'loading'
        return axios.get('https://rickandmortyapi.com/api/character')
          .then(response => {
            loadingState.value = 'success'
            characters.value = response.data.results
          })
      }
      const orderKey = ref('id')
      const charactersOrdered = computed(() => {
        return orderBy(characters.value, orderKey.value)
      })

      const setOrderKey = (key) => {
        orderKey.value = key
      }
      return {characters, loadingState, fetchAllCharacters, charactersOrdered, orderKey, setOrderKey}
    },
    created () {
      this.fetchAllCharacters()
    }
  }

Organise Code By Feature

Render Context

Fetch Resource Feature

Order Array Feature

Code Organisation

By Options VS By Feature

♻️ Logic Reuse

<script>
  import {computed, ref} from 'vue'
  const useCounter = () => {
    const count = ref(0)
    const double = computed(() => count.value * 2)
    const increaseCount = () => {
      count.value++
    }

    return {count, double, increaseCount}
  }
  export default {
    setup () {
      const {increaseCount, count, double} = useCounter()
      return {increaseCount, count, double} // render context
    }
  }
</script>

Logic Reuse

<script>
  import {computed, ref} from 'vue'
  const useCounter = (initial = 0) => {
    const count = ref(initial)
    const double = computed(() => count.value * 2)
    const increaseCount = () => {
      count.value++
    }

    return {count, double, increaseCount}
  }
  export default {
    setup () {
      const {increaseCount, count, double} = useCounter(40)
      return {increaseCount, count, double}
    }
  }
</script>

Logic Reuse

Can extract to another file

Logic Reuse

Fetch Data

The Component

<template>
  <div>
    <div
      v-for="character in characters"
      :key="character.id"
    >
      <!--  character card   -->
    </div>
    
    <div v-if="loadingState === 'loading'">Loading...</div>
  </div>
</template>    

CharacterCards.vue

Fetch Data

The Component

import axios from 'axios'
export default {
  data () {
    return {
      characters: [],
      loadingState: null,
    }
  },
  methods: {
    fetchCharacters () {
      this.loadingState = 'loading'
      axios.get('https://rickandmortyapi.com/api/character')
        .then(response => {
          this.loadingState = 'success'
          this.characters = response.data.results
      	})
    }
  },
  created () {
    this.fetchCharacters()
  }
}

CharacterCards.vue

fetchResource function

import {ref} from 'vue'
import axios from 'axios'

export default function useFetchResource (url) {
  const data = ref([])
  const loadingState = ref(null)

  const fetchResource = () => {
    loadingState.value = 'loading'
    return axios.get(url)
      .then(response => {
        loadingState.value = 'success'
        data.value = response.data.results
      })
  }

  return {data, loadingState, fetchResource}
}

fetchResource.js

The Component

<script>
  import useFetchResource from '../use/fetchResource'
  export default {
    setup () {
      const {data, loadingState, fetchResource} = useFetchResource('rickandmortyapi.com/...')

      return {
        characters: data,
        loadingState,
        fetchAllCharacters: fetchResource
      }
    },
    created () {
      this.fetchAllCharacters()
    }
  }
</script>

CharacterCards.vue

<template></template>


<script>
  import useMousePosition from '../use/mousePosition'

  export default {
    setup () {
      const {x, y} = useMousePosition()

      // ...
    }
  }
</script>

🐭 Logic Reuse

🐭 Logic Reuse

Logic Reuse Alternatives

  • Mixins
  • Higher Order Components
  • Renderless Components

Respective Drawbacks when compared with the Composition API

Composition API Benefits

  • extremely flexible
  • clear source of properties
  • performance
  • no namespace collision

Drawbacks of Composition API

(own opinion)

  • overhead of introducing refs

  • no shared template

  • learning curve

Consider 🙏

Consider 🙏

  • no need to rewrite your Vue 2 app
  • no need to use it in a simple component
  • keep the junior devs in mind

(own opinion)

Good Fit For

  • component code grows too long
  • team that work on the same (big) components
  • reuse component options without using mixins
  • when TypeScript support is important

(own opinion)

I do Videos + Workshops

vueschool.io

$25 Free Pass

vueschool.io

Check your 👜

vueschool.io         @vueschool_io

@hootlex

Vue.js 3 courses
coming soon

🕺

$25 Free Pass

vueschool.io

Booth

Thank You

Vue 3 and the Composition API - Vue Toronto

By Alex Kyriakidis

Vue 3 and the Composition API - Vue Toronto

Vue 3 and the Composition API

  • 14,503