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