[Vue] What is a Composable?

Composables are, by far, the best way to organize business logic in your Vue 3 app.

They let you extract small pieces of logic into functions that you can easily reuse repeatedly. This makes your code easier to write and read.

Since this way of writing Vue code is relatively new, you might be wondering what the best practices are when writing composables. This course will serve as your guide on how to craft solid composables that you and your team can rely on.

First, though, we need to make sure we’re on the same page. So let me take a bit to explain what, exactly, a composable is.


What is a Composable?

According to the Vue documentation, a composable is “a function that leverages Vue Composition API to encapsulate and reuse stateful logic”. If you’re not yet familiar with the composition API, or want to learn more about the advantages of using composables.

Any code that uses reactivity can be turned into a composable.

Here’s a simple example of a useMouse composable from the Vue.js docs:

import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {
  const x = ref(0)
  const y = ref(0)

  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  return { x, y }
}

We define our state as refs, then update that state whenever the mouse moves. By returning the x and y refs, we can use them inside of any component (or even another composable).

Here’s how we’d use this composable inside of a component:

<script setup>
  import { useMouse } from './composables/mouse';
  const { x, y } = useMouse();
</script>

<template>
  Mouse position is at: {{ x }}, {{ y }}
</template>

As you can see, using the useMouse composable allows us to easily reuse all of this logic. With very little extra code, we’re able to grab the mouse coordinates in our component.

Now that we’re on the same page, let’s start to think about how we should create composable inputs.

 

How to create composable inputs?

There are a few ways we could do it. We could use an argument for each property:

const title = useTitle('Product Page', true, '%s | My Socks Store')

We could also use an options argument:

const title = useTitle({ title: 'Product Page', 
                         observe: true, 
                         titleTemplate: '%s | Socks Store' })

The benefit here is we don’t have to remember the correct ordering, we know what each option does, and easier to add new options.

Or we could use a combination of both:

const title = useTitle('Product Page', { observe: true, 
                                         titleTemplate: '%s | Socks Store' })

Here we are putting the required arguments first and the other arguments are optional.

It’ll also be much easier to add new options later on. This applies both to adding new options to the composable itself, and to adding options when using the composable.

So, using an options object is great. But how do we implement that, and parse them out.


How to parse the options argument?

Here’s how you would implement the options object pattern in a composable:

export function useTitle(newTitle, options) {
    const {
      observe = false,
      titleTemplate = '%s',
    } = options;
    
    // ...
  }

Here, we can accept newTitle (our required argument), and then the last argument is the options object. The next step is to destructure the options object. By destructuring, we can access all the values, and clearly provide defaults for each possible option.

posted @   Zhentiw  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2023-02-04 [Docker] Remove all containers and images
2023-02-04 [Docker] Build multi stage image
2022-02-04 [RxJS] Using iif
2020-02-04 [NestJS] NestJs Data Validation with ValidationPipe
2016-02-04 [Unit Testing] Based on input value, spyOn function
2016-02-04 [Cycle.js] Generalizing run() function for more types of sources
2016-02-04 [Redux] Extracting Container Components -- Complete
点击右上角即可分享
微信分享提示