Hunter Middleton

Vue.js the guide

Practical Guide to Vue.js

Global API

Let's start at the entry point of our application, the main.js file. Mounting looks like this:

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.mount('#app')

Composition API

Inspired by React, Vue offers a Composition API | "hook"functions. Vue components themself are very flexible and re-usable. With the use of a new API you can go one step further. Compsotion API can be very beneficial in larger applications. I will illustrate it with a simple example.

The first traditional way, a simple component that fetches and displays some data:

<script>
import { fetchResources } from '@/actions'
import ResourceDetail from '@/components/ResourceDetail'
import ResourceList from '@/components/ResourceList'
export default {
components: {
ResourceDetail,
ResourceList,
},
data() {
return {
title: 'Your resources',
selectedResource: null,
resources: []
}
},
async created() {
this.resources = await fetchResources()
},
computed: {
hasResources() {
return this.resourceCount > 0
},
activeResource() {
return this.selectedResource || (this.hasResources && this.resources[0]) || null
},
resourceCount(){
return this.resources.length
}
},
methods: {
selectResource(resource) {
this.selectedResource = {...resource}
}
}
}
</script>

Let's use composition API now, first check the code then the explanation.

import { ref, onMounted, computed } from 'vue'
import { fetchResources } from '@/actions'

export default function useResources() {
const resources = ref([])
const getResources = async () => resources.value = await fetchResources()

onMounted(getResources);

const resourceCount = computed(() => resources.value.length)
const hasResources = computed(() => resourceCount.value > 0 )

return {
resources,
resourceCount,
hasResources
}
}

Here you can see a very simple composition function responsible for fetching resources data. Composition functions usually start with the "use" keyword so developeres will know it's not just an ordinary function.

  1. "ref" will create a reactive object. If you want to get a raw value from the ref, you need to access it under the "value" property. See the following example:
var a = 7;
var b = a;
b = 10;
// a = 7
// b = 10

var a = ref(7);
var b = a;
b.value = 100;
// a = 100
// b = 100

That's why I have created a resource array as a ref. If an item from the array gets added or removed we want to reflect these changes in our application.

  1. getResources will just fetch the data and assign it to resources.

  2. onMounted lifecycle function will be called when a component will be added to the DOM.

  3. computed properties are evaluated when their dependencies(resourceCount or resources) change.

  4. In the last step we will return data/functions that we want to expose to a component that will use useResources hook function.

Now is the time to hook-in the composition function.

<script>
import ResourceDetail from '@/components/ResourceDetail'
import ResourceList from '@/components/ResourceList'
import useResources from '@/composition/useResources';
export default {
components: {
ResourceDetail,
ResourceList,
},
data() {
return {
title: 'Your resources',
selectedResource: null
}
},
setup() {
return {
...useResources()
}
},
computed: {
activeResource() {
return this.selectedResource || (this.hasResources && this.resources[0]) || null
}
},
methods: {
selectResource(resource) {
this.selectedResource = {...resource}
}
}
}
</script>

As you can see here I am calling useResources in the new setup function.

That's why we can access all computed properties and resources data as before. Now they are providewd with the return of useResources function.