状态复用
Vue 状态复用指将组件状态逻辑抽取为可复用的单元,在多个组件间共享状态和行为。
Composables 复用
基础 Composable
JavaScript
// composables/useCounter.js
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const doubleCount = computed(() => count.value * 2)
const increment = () => {
count.value++
}
const decrement = () => {
count.value--
}
return {
count,
doubleCount,
increment,
decrement
}
}
组件中使用
vue
<script setup>
import { useCounter } from '@/composables/useCounter'
const { count, doubleCount, increment, decrement } = useCounter(10)
</script>
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double: {{ doubleCount }}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
每个组件调用
useCounter()会创建独立的状态实例,互不影响。
共享状态 Composable
模块级单例
JavaScript
// composables/useSharedState.js
import { ref } from 'vue'
// 模块级变量,所有组件共享同一实例
const sharedCount = ref(0)
export function useSharedState() {
const increment = () => {
sharedCount.value++
}
return {
sharedCount,
increment
}
}
多组件共享
vue
<!-- ComponentA.vue -->
<script setup>
import { useSharedState } from '@/composables/useSharedState'
const { sharedCount, increment } = useSharedState()
</script>
<!-- ComponentB.vue -->
<script setup>
import { useSharedState } from '@/composables/useSharedState'
const { sharedCount } = useSharedState()
</script>
模块级变量在应用生命周期内只初始化一次,多组件共享同一状态。
Provide / Inject
祖先组件 Provide
vue
<!-- Parent.vue -->
<script setup>
import { provide, ref } from 'vue'
const theme = ref('light')
provide('theme', {
current: theme,
toggle: () => {
theme.value = theme.value === 'light' ? 'dark' : 'light'
}
})
</script>
后代组件 Inject
vue
<!-- Child.vue -->
<script setup>
import { inject } from 'vue'
const { current, toggle } = inject('theme')
</script>
<template>
<div :class="current">
<button @click="toggle">切换主题</button>
</div>
</template>
provide/inject适用于深层组件通信,避免逐层传递 props。
组合使用场景
Composable + Provide
JavaScript
// composables/useAuth.js
import { ref, provide, inject } from 'vue'
const SymbolKey = Symbol('auth')
export function createAuthProvider(user) {
const currentUser = ref(user)
const login = (userData) => {
currentUser.value = userData
}
const logout = () => {
currentUser.value = null
}
provide(SymbolKey, {
currentUser,
login,
logout
})
}
export function useAuth() {
return inject(SymbolKey)
}
对比选择
| 方案 | 适用场景 | 状态共享 | 类型安全 |
|---|---|---|---|
| Composables | 逻辑复用 | 可选 | 强 |
| Provide/Inject | 深层组件通信 | 是 | 中 |
| Pinia/Vuex | 全局状态管理 | 是 | 强 |
注意事项
- Composable 函数必须以
use开头,遵循 Vue 命名约定 - 共享状态需注意避免意外修改导致组件间状态污染
provide/inject不适合高频更新状态,性能较差- 复杂应用建议使用 Pinia 等状态管理库
要点总结
- Composables 是 Vue 3 推荐的状态复用方案,逻辑与状态可一并复用
- 模块级变量实现共享状态,多组件共享同一实例
provide/inject适用于祖先-后代组件通信- 简单逻辑用 Composables,全局状态用 Pinia
存放路径: articles/VUE/进阶/过度动画与状态复用/状态复用.md
📝 发现内容有误?点击此处直接编辑