阿里云主机折上折
  • 微信号
Current Site:Index > Advanced usage of Composition API

Advanced usage of Composition API

Author:Chuan Chen 阅读数:46280人阅读 分类: Vue.js

Core Concepts of Composition API

The Composition API is a new programming paradigm introduced in Vue 3, which organizes component logic in a functional way. Unlike the Options API, the Composition API groups related code together instead of scattering it across different option blocks.

import { ref, computed } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const double = computed(() => count.value * 2)
    
    function increment() {
      count.value++
    }
    
    return {
      count,
      double,
      increment
    }
  }
}

Reactive State Management

In-Depth Usage of ref and reactive

ref and reactive are the two primary ways to create reactive data. ref is suitable for primitive types and object references, while reactive is specifically for objects.

import { ref, reactive } from 'vue'

const user = reactive({
  name: 'Zhang San',
  age: 25,
  address: {
    city: 'Beijing',
    street: 'Chaoyang District'
  }
})

const counter = ref(0)

// Accessing ref values requires .value
console.log(counter.value) // 0

// Reactive objects can be accessed directly
console.log(user.name) // Zhang San

Reactive Utility Functions

Vue provides a series of utility functions to handle reactive data:

import { isRef, unref, toRef, toRefs } from 'vue'

const count = ref(0)
console.log(isRef(count)) // true

// unref automatically unwraps refs
function useValue(maybeRef) {
  return unref(maybeRef)
}

// Convert a reactive object's property to a ref
const userRef = toRef(user, 'name')

// Convert all properties of a reactive object to refs
const { name, age } = toRefs(user)

Composable Functions

Composable functions are the core abstraction mechanism of the Composition API, allowing us to extract reusable logic into separate functions.

Creating Custom Composable Functions

// useMouse.js
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 }
}

// Usage in a component
import { useMouse } from './useMouse'

export default {
  setup() {
    const { x, y } = useMouse()
    return { x, y }
  }
}

Composable Functions with Parameters

// useFetch.js
import { ref } from 'vue'

export function useFetch(url) {
  const data = ref(null)
  const error = ref(null)
  const loading = ref(false)
  
  async function fetchData() {
    loading.value = true
    try {
      const response = await fetch(url)
      data.value = await response.json()
    } catch (err) {
      error.value = err
    } finally {
      loading.value = false
    }
  }
  
  fetchData()
  
  return { data, error, loading, retry: fetchData }
}

Advanced Usage of Lifecycle Hooks

The Composition API provides a more flexible way to manage lifecycles:

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

export default {
  setup() {
    onMounted(() => {
      console.log('Component mounted')
    })
    
    onUpdated(() => {
      console.log('Component updated')
    })
    
    onUnmounted(() => {
      console.log('Component unmounted')
    })
  }
}

Multiple Hooks with the Same Name

The Composition API allows registering multiple lifecycle hooks with the same name, which will be called in the order they were registered:

setup() {
  onMounted(() => console.log('First mounted hook'))
  onMounted(() => console.log('Second mounted hook'))
}

In-Depth Usage of Dependency Injection

provide and inject enable cross-level component communication:

// Ancestor component
import { provide, ref } from 'vue'

export default {
  setup() {
    const theme = ref('dark')
    
    provide('theme', theme)
    
    return {
      theme
    }
  }
}

// Descendant component
import { inject } from 'vue'

export default {
  setup() {
    const theme = inject('theme', 'light') // Default value 'light'
    
    return {
      theme
    }
  }
}

Reactive Injection

// Provide a reactive value
const counter = ref(0)
provide('counter', counter)

// Inject and maintain reactivity
const injectedCounter = inject('counter')

Template Refs and Component Refs

In the Composition API, DOM elements or component instances are accessed via ref:

import { ref, onMounted } from 'vue'

export default {
  setup() {
    const inputRef = ref(null)
    
    onMounted(() => {
      inputRef.value.focus()
    })
    
    return {
      inputRef
    }
  },
  template: `<input ref="inputRef">`
}

Exposing Component Methods

Child components can explicitly expose methods using expose:

// Child component
import { ref } from 'vue'

export default {
  setup(props, { expose) {
    const count = ref(0)
    
    function increment() {
      count.value++
    }
    
    expose({
      increment
    })
    
    return {
      count
    }
  }
}

// Parent component
const childRef = ref(null)

function callChildMethod() {
  childRef.value.increment()
}

Render Functions and JSX

The Composition API allows direct use of render functions:

import { h, ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    
    return () => h('div', [
      h('button', {
        onClick: () => count.value++
      }, 'Increment'),
      h('span', `Current count: ${count.value}`)
    ])
  }
}

JSX Support

import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    
    return () => (
      <div>
        <button onClick={() => count.value++}>Increment</button>
        <span>Current count: {count.value}</span>
      </div>
    )
  }
}

Custom Directives

Creating custom directives in the Composition API:

import { directive } from 'vue'

const vFocus = {
  mounted(el) {
    el.focus()
  }
}

// Usage
export default {
  directives: {
    focus: vFocus
  },
  setup() {
    return {}
  }
}

Global Directives

// main.js
import { createApp } from 'vue'

const app = createApp(App)

app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

Performance Optimization Techniques

Computed Property Caching

import { computed, ref } from 'vue'

export default {
  setup() {
    const firstName = ref('Zhang')
    const lastName = ref('San')
    
    const fullName = computed(() => `${firstName.value}${lastName.value}`)
    
    return {
      fullName
    }
  }
}

Debouncing and Throttling

import { ref } from 'vue'
import { debounce } from 'lodash-es'

export default {
  setup() {
    const searchQuery = ref('')
    
    const debouncedSearch = debounce(() => {
      console.log('Search:', searchQuery.value)
    }, 500)
    
    function onInput() {
      debouncedSearch()
    }
    
    return {
      searchQuery,
      onInput
    }
  }
}

TypeScript Integration

The Composition API integrates well with TypeScript:

import { ref, computed } from 'vue'

interface User {
  name: string
  age: number
}

export default {
  setup() {
    const user = ref<User>({
      name: 'Zhang San',
      age: 25
    })
    
    const nextYearAge = computed(() => user.value.age + 1)
    
    return {
      user,
      nextYearAge
    }
  }
}

Type Inference

import { ref } from 'vue'

const count = ref(0) // Inferred as Ref<number>

count.value = '1' // Type error

State Management Integration

The Composition API can easily integrate with state management libraries like Pinia:

// store/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++
    }
  }
})

// Usage in a component
import { useCounterStore } from '@/stores/counter'

export default {
  setup() {
    const counter = useCounterStore()
    
    return {
      counter
    }
  }
}

Async Components and Suspense

The Composition API supports async components:

import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  import('./components/AsyncComponent.vue')
)

export default {
  components: {
    AsyncComp
  },
  setup() {
    return {}
  }
}

Suspense Integration

<template>
  <Suspense>
    <template #default>
      <AsyncComponent />
    </template>
    <template #fallback>
      <div>Loading...</div>
    </template>
  </Suspense>
</template>

<script>
import { defineAsyncComponent } from 'vue'

export default {
  components: {
    AsyncComponent: defineAsyncComponent(() =>
      import('./AsyncComponent.vue')
    )
  }
}
</script>

Custom Composition API Libraries

Organizing multiple composable functions into a library:

// composables/index.js
export * from './useMouse'
export * from './useFetch'
export * from './useLocalStorage'

// Usage in a component
import { useMouse, useFetch } from '@/composables'

export default {
  setup() {
    const { x, y } = useMouse()
    const { data } = useFetch('/api/data')
    
    return {
      x,
      y,
      data
    }
  }
}

Reactive CSS Variables

The Composition API can dynamically generate CSS variables:

import { ref, watchEffect } from 'vue'

export default {
  setup() {
    const themeColor = ref('#42b983')
    
    watchEffect(() => {
      document.documentElement.style.setProperty(
        '--theme-color',
        themeColor.value
      )
    })
    
    return {
      themeColor
    }
  }
}

Server-Side Rendering (SSR) Support

Special handling for the Composition API in SSR environments:

import { ref, onServerPrefetch } from 'vue'
import { fetchData } from './api'

export default {
  setup() {
    const data = ref(null)
    
    onServerPrefetch(async () => {
      data.value = await fetchData()
    })
    
    return {
      data
    }
  }
}

Debugging Techniques

The Composition API provides debugging tools:

import { debug } from 'vue'

export default {
  setup() {
    const count = ref(0)
    
    debug(count) // Output reactive data changes in the console
    
    return {
      count
    }
  }
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:热模块替换支持

下一篇:自定义hook开发

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.