Vue 3 Composition API深度探索与最佳实践
·
Vue 3 Composition API深度探索与最佳实践
引言
Vue 3的Composition API是框架演进中的重要里程碑,它提供了更灵活的逻辑组织和复用方式。本文将深入探讨Composition API的设计理念、核心特性以及在实际项目中的最佳实践。
Composition API vs Options API
逻辑关注点分离
Options API按照选项类型组织代码,导致相同逻辑分散在不同选项中:
// Options API方式
export default {
data() {
return {
posts: [],
currentPage: 1
}
},
computed: {
paginatedPosts() {
// 分页逻辑
}
},
methods: {
fetchPosts() {
// 获取数据逻辑
}
},
mounted() {
this.fetchPosts()
}
}
Composition API则按照逻辑功能组织代码:
// Composition API方式
import { ref, computed, onMounted } from 'vue'
export default {
setup() {
const posts = ref([])
const currentPage = ref(1)
const paginatedPosts = computed(() => {
// 分页逻辑
return posts.value.slice(0, 10)
})
const fetchPosts = async () => {
// 获取数据逻辑
}
onMounted(fetchPosts)
return {
posts,
currentPage,
paginatedPosts,
fetchPosts
}
}
}
更好的TypeScript支持
Composition API天然支持类型推断,提供了更好的TypeScript开发体验:
interface User {
id: number
name: string
email: string
}
export default defineComponent({
setup() {
const user = ref<User | null>(null)
const loading = ref<boolean>(false)
const fetchUser = async (id: number): Promise<void> => {
// 类型安全的API调用
}
return {
user,
loading,
fetchUser
}
}
})
自定义组合函数:逻辑复用的艺术
Composition API最强大的特性是能够创建自定义组合函数,实现跨组件逻辑复用:
// usePagination.js
import { ref, computed } from 'vue'
export function usePagination(items, itemsPerPage = 10) {
const currentPage = ref(1)
const totalPages = computed(() =>
Math.ceil(items.value.length / itemsPerPage)
)
const paginatedItems = computed(() => {
const start = (currentPage.value - 1) * itemsPerPage
const end = start + itemsPerPage
return items.value.slice(start, end)
})
function nextPage() {
if (currentPage.value < totalPages.value) {
currentPage.value++
}
}
function prevPage() {
if (currentPage.value > 1) {
currentPage.value--
}
}
return {
currentPage,
totalPages,
paginatedItems,
nextPage,
prevPage
}
}
在组件中使用:
import { usePagination } from '@/composables/usePagination'
export default {
setup() {
const items = ref([...]) // 数据源
const {
currentPage,
totalPages,
paginatedItems,
nextPage,
prevPage
} = usePagination(items, 20)
return {
currentPage,
totalPages,
paginatedItems,
nextPage,
prevPage
}
}
}
响应式进阶技巧
响应式工具函数
Vue 3提供了一系列响应式工具函数:
import {
isRef,
unref,
toRef,
toRefs,
customRef
} from 'vue'
// 自定义ref实现防抖
function useDebouncedRef(value, delay = 200) {
let timeout
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}
})
}
Effect Scope管理副作用
Vue 3.2引入了effectScopeAPI,用于集中管理副作用:
import { effectScope, onScopeDispose } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
const scope = effectScope()
scope.run(() => {
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
})
// 停止所有副作用
const stop = () => scope.stop()
onScopeDispose(stop)
return { x, y, stop }
}
性能优化与最佳实践
1. 合理使用ref和reactive
- 使用
ref处理基本类型和对象引用替换 - 使用
reactive处理不需要引用替换的对象
2. 减少不必要的响应式开销
// 不佳:创建了不必要的响应式对象
const state = reactive({
largeData: bigData // bigData很大且不需要响应式
})
// 更佳:分离响应式和非响应式数据
const state = reactive({
// 只有需要响应式的数据才放在这里
})
const nonReactiveData = ref(bigData) // 或直接使用原始数据
3. 使用provide/inject进行跨组件状态共享
// 父组件
import { provide, reactive } from 'vue'
export default {
setup() {
const globalState = reactive({
user: null,
theme: 'light'
})
provide('globalState', globalState)
return { globalState }
}
}
// 子组件
import { inject } from 'vue'
export default {
setup() {
const globalState = inject('globalState')
return { globalState }
}
}
结语
Composition API为Vue应用开发带来了全新的编程模式和可能性。通过合理利用组合函数、响应式工具和性能优化技巧,我们可以构建出更健壮、可维护和高性能的Vue应用。随着Vue生态的不断发展,Composition API将成为Vue开发的标准方式,值得每位Vue开发者深入学习和掌握。
更多推荐
所有评论(0)