Vue3$Data-Composables

102 阅读1分钟

Vue3$Data-Composables

0. What is a "Composable"?

Composable 组合式函数:一个利用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。(官网)

我对 Composable 的理解:它是一个函数,目的是封装数据(及其方法)。重点在于数据(状态)。

  • 这个函数包含了某些数据的所有方法,同时 return 了出去。(design)
  • 在 template 或者 script 中就可以使用这些数据和方法。(use)

1. Examples

1.1 useMouse with useEventListener

// @file event.js
import { onMounted, onUnmounted } from 'vue'

export function useEventListener(target, event, callback) {
  // if you want, you can also make this
  // support selector strings as target
  onMounted(() => target.addEventListener(event, callback))
  onUnmounted(() => target.removeEventListener(event, callback))
}
// @file mouse.js
import { ref } from 'vue'
import { useEventListener } from './event'

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

  useEventListener(window, 'mousemove', (event) => {
    x.value = event.pageX
    y.value = event.pageY
  })

  return { x, y }
}
<script setup>
import { useMouse } from './mouse.js'

const { x, y } = useMouse()
</script>

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

1.2 Async State Example

  1. 定义的时候使用 toValue()watchEffect() 实现响应式
  2. 使用的时候接收 ref 或者 getter()
// @file fetch.js
import { ref, watchEffect, toValue } from 'vue'

export function useFetch(url) {
  const data = ref(null)
  const error = ref(null)

  const fetchData = () => {
    // reset state before fetching..
    data.value = null
    error.value = null

    fetch(toValue(url)) // 2. use toValue to get the reactive state's value (ref / getter)
      .then((res) => res.json())
      .then((json) => (data.value = json))
      .catch((err) => (error.value = err))
  }

  watchEffect(() => { // 1. use watchEffect to call the function
    fetchData()
  })

  return { data, error }
}
const url = ref('/initial-url')

const { data, error } = useFetch(url)

// this should trigger a re-fetch
url.value = '/new-url'
// re-fetch when props.id changes
const { data, error } = useFetch(() => `/posts/${props.id}`)

2. Conventions and Best Practices

0. Naming

export function useXxx()

1. Input Arguments

refs / getters ==> toValue() && watchEffect()

2. Return Values

1. Define return values (as refs of an object)

composables: always return a plain, non-reactive object containing multiple refs.
// x and y are refs
const { x, y } = useMouse()

2. Receive return values (can be a reactive object)

If you prefer to use returned state from composables as object properties, you can wrap the returned object with reactive() so that the refs are unwrapped. (why reactive, not plain object? ==> if plain, page will not be reative)
const mouse = reactive(useMouse())
// mouse.x is linked to original ref
console.log(mouse.x)

Links

VueComposables

VueUse