Vue.js version 3 introduced a new way of writing Vue components called Composition API. Since version 3.2 Vue.js release <script setup>
as a new way for writing Vue components. In this lesson, we will combine <script setup>
with the composables to write reusable code.
First, let's create a composable. Create a new file resources/js/composables/posts.js
and put code inside.
resources/js/composables/posts.js:
import { ref } from 'vue' export default function usePosts() { const posts = ref([])}
In this composable first, we import the ref
. Ref means reference which will make posts variable reactive.
Then as in every file, we need to export default. In our case, we will export the result of the function usePosts
. Such useXyz()
is the default naming convention name that starts with the use
.
Next, we need to add an async method for getting the posts.
resources/js/composables/posts.js:
import { ref } from 'vue' export default function usePosts() { const posts = ref([]) const getPosts = async () => { axios.get('/api/posts') .then(response => { posts.value = response.data; }) } }
And all the exposed states need to be returned. Now we have posts
and getPosts
.
resources/js/composables/posts.js:
import { ref } from 'vue' export default function usePosts() { const posts = ref([]) const getPosts = async () => { axios.get('/api/posts') .then(response => { posts.value = response.data; }) } return { posts, getPosts } }
Now we need to change the Vue component. Instead of <script>
use <script setup>
and use just created composable.
resources/js/components/Posts/Index.vue:
<template> // ...</template> <script setup> import { onMounted } from "vue";import usePosts from "../../composables/posts"; const { posts, getPosts } = usePosts()onMounted(() => { getPosts()})</script><script> export default { data() { return { posts: [] } }, mounted() { this.fetchPosts() }, methods: { fetchPosts() { axios.get('/api/posts') .then(response => this.posts = response.data) .catch(error => console.log(error)) } }}</script>
As you can see, this way we need to write less code in the Vue component itself, and also everything in the composable can be reused in other components.
In other words, composable is an equivalent of Service class in PHP/Laravel, and Vue component is using the Service method, like a Laravel Controller.
We can improve importing files instead of going back directories with dots like ../../
we can change it to the @
sign.
To do this, we need to add a new alias to the vite config.
vite.config.js:
import { defineConfig } from 'vite';import laravel from 'laravel-vite-plugin';import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [ laravel({ input: [ 'resources/css/app.css', 'resources/js/app.js', ], refresh: true, }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), ], resolve: { alias: { vue: 'vue/dist/vue.esm-bundler.js', '@': '/resources/js', }, },});
Now we can import like this:
resources/js/components/Posts/Index.vue:
import usePosts from "../../composables/posts"; import usePosts from "@/composables/posts";
One more tip here. Importing files this way your IDE might complain. But we can easily fix it by creating a file jsconfig.json
with the code:
jsconfig.json:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["resources/js/*"] } }, "exclude": ["node_modules", "public"]}
In the next lessons, I will be using the <script setup>
syntax and will be importing with the @
alias.