Composition API高级用法
组合式API的核心概念
组合式API是Vue 3引入的全新编程范式,它通过函数式的方式组织组件逻辑。与选项式API不同,组合式API将相关代码组织在一起,而不是分散在不同的选项块中。
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
}
}
}
响应式状态管理
ref与reactive的深度使用
ref
和reactive
是创建响应式数据的两种主要方式。ref
适用于基本类型和对象引用,而reactive
专门用于对象。
import { ref, reactive } from 'vue'
const user = reactive({
name: '张三',
age: 25,
address: {
city: '北京',
street: '朝阳区'
}
})
const counter = ref(0)
// 访问ref值需要.value
console.log(counter.value) // 0
// reactive对象可以直接访问
console.log(user.name) // 张三
响应式工具函数
Vue提供了一系列工具函数来处理响应式数据:
import { isRef, unref, toRef, toRefs } from 'vue'
const count = ref(0)
console.log(isRef(count)) // true
// unref自动解包ref
function useValue(maybeRef) {
return unref(maybeRef)
}
// 将reactive对象的属性转换为ref
const userRef = toRef(user, 'name')
// 将reactive对象的所有属性转换为ref
const { name, age } = toRefs(user)
组合式函数
组合式函数是组合式API的核心抽象机制,它允许我们将可复用的逻辑提取到单独的函数中。
创建自定义组合式函数
// 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 }
}
// 在组件中使用
import { useMouse } from './useMouse'
export default {
setup() {
const { x, y } = useMouse()
return { x, y }
}
}
带参数的组合式函数
// 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 }
}
生命周期钩子的高级用法
组合式API提供了更灵活的生命周期管理方式:
import { onMounted, onUpdated, onUnmounted } from 'vue'
export default {
setup() {
onMounted(() => {
console.log('组件挂载')
})
onUpdated(() => {
console.log('组件更新')
})
onUnmounted(() => {
console.log('组件卸载')
})
}
}
多个同名钩子
组合式API允许注册多个同名生命周期钩子,它们将按注册顺序依次调用:
setup() {
onMounted(() => console.log('第一个挂载钩子'))
onMounted(() => console.log('第二个挂载钩子'))
}
依赖注入的深度使用
provide
和inject
可以实现跨层级组件通信:
// 祖先组件
import { provide, ref } from 'vue'
export default {
setup() {
const theme = ref('dark')
provide('theme', theme)
return {
theme
}
}
}
// 后代组件
import { inject } from 'vue'
export default {
setup() {
const theme = inject('theme', 'light') // 默认值'light'
return {
theme
}
}
}
响应式注入
// 提供响应式值
const counter = ref(0)
provide('counter', counter)
// 注入并保持响应性
const injectedCounter = inject('counter')
模板引用与组件引用
组合式API中通过ref
获取DOM元素或组件实例:
import { ref, onMounted } from 'vue'
export default {
setup() {
const inputRef = ref(null)
onMounted(() => {
inputRef.value.focus()
})
return {
inputRef
}
},
template: `<input ref="inputRef">`
}
组件方法暴露
子组件可以通过expose
明确暴露哪些方法:
// 子组件
import { ref } from 'vue'
export default {
setup(props, { expose) {
const count = ref(0)
function increment() {
count.value++
}
expose({
increment
})
return {
count
}
}
}
// 父组件
const childRef = ref(null)
function callChildMethod() {
childRef.value.increment()
}
渲染函数与JSX
组合式API中可以直接使用渲染函数:
import { h, ref } from 'vue'
export default {
setup() {
const count = ref(0)
return () => h('div', [
h('button', {
onClick: () => count.value++
}, '增加'),
h('span', `当前计数: ${count.value}`)
])
}
}
JSX支持
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return () => (
<div>
<button onClick={() => count.value++}>增加</button>
<span>当前计数: {count.value}</span>
</div>
)
}
}
自定义指令
组合式API中创建自定义指令:
import { directive } from 'vue'
const vFocus = {
mounted(el) {
el.focus()
}
}
// 使用
export default {
directives: {
focus: vFocus
},
setup() {
return {}
}
}
全局指令
// main.js
import { createApp } from 'vue'
const app = createApp(App)
app.directive('focus', {
mounted(el) {
el.focus()
}
})
性能优化技巧
计算属性的缓存
import { computed, ref } from 'vue'
export default {
setup() {
const firstName = ref('张')
const lastName = ref('三')
const fullName = computed(() => `${firstName.value}${lastName.value}`)
return {
fullName
}
}
}
防抖与节流
import { ref } from 'vue'
import { debounce } from 'lodash-es'
export default {
setup() {
const searchQuery = ref('')
const debouncedSearch = debounce(() => {
console.log('搜索:', searchQuery.value)
}, 500)
function onInput() {
debouncedSearch()
}
return {
searchQuery,
onInput
}
}
}
TypeScript集成
组合式API与TypeScript有很好的集成:
import { ref, computed } from 'vue'
interface User {
name: string
age: number
}
export default {
setup() {
const user = ref<User>({
name: '张三',
age: 25
})
const nextYearAge = computed(() => user.value.age + 1)
return {
user,
nextYearAge
}
}
}
类型推断
import { ref } from 'vue'
const count = ref(0) // 推断为Ref<number>
count.value = '1' // 类型错误
状态管理集成
组合式API可以轻松集成Pinia等状态管理库:
// store/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
actions: {
increment() {
this.count++
}
}
})
// 组件中使用
import { useCounterStore } from '@/stores/counter'
export default {
setup() {
const counter = useCounterStore()
return {
counter
}
}
}
异步组件与Suspense
组合式API支持异步组件:
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() =>
import('./components/AsyncComponent.vue')
)
export default {
components: {
AsyncComp
},
setup() {
return {}
}
}
Suspense集成
<template>
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>加载中...</div>
</template>
</Suspense>
</template>
<script>
import { defineAsyncComponent } from 'vue'
export default {
components: {
AsyncComponent: defineAsyncComponent(() =>
import('./AsyncComponent.vue')
)
}
}
</script>
自定义组合式API库
将多个组合式函数组织成库:
// composables/index.js
export * from './useMouse'
export * from './useFetch'
export * from './useLocalStorage'
// 组件中使用
import { useMouse, useFetch } from '@/composables'
export default {
setup() {
const { x, y } = useMouse()
const { data } = useFetch('/api/data')
return {
x,
y,
data
}
}
}
响应式CSS变量
组合式API可以动态生成CSS变量:
import { ref, watchEffect } from 'vue'
export default {
setup() {
const themeColor = ref('#42b983')
watchEffect(() => {
document.documentElement.style.setProperty(
'--theme-color',
themeColor.value
)
})
return {
themeColor
}
}
}
服务端渲染(SSR)支持
组合式API在SSR环境下的特殊处理:
import { ref, onServerPrefetch } from 'vue'
import { fetchData } from './api'
export default {
setup() {
const data = ref(null)
onServerPrefetch(async () => {
data.value = await fetchData()
})
return {
data
}
}
}
调试技巧
组合式API提供了调试工具:
import { debug } from 'vue'
export default {
setup() {
const count = ref(0)
debug(count) // 在控制台输出响应式数据的变化
return {
count
}
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn