Vue3组合式API使用心得与踩坑记录

1. 响应式系统使用技巧

1.1 ref vs reactive


// ref 适用场景
const count = ref(0)
const name = ref('张三')
const isActive = ref(true)

// reactive 适用场景
const state = reactive({
    user: {
        name: '张三',
        age: 25
    },
    settings: {
        theme: 'dark'
    }
})

// 错误示范
const { name } = reactive({ name: '张三' }) // 解构后失去响应性
const name = ref(reactive({ value: '张三' })) // 嵌套使用,过度复杂
                        

常见陷阱

  • 解构reactive对象会失去响应性
  • ref在模板中自动解包,但在JS中需要.value
  • reactive不能用于原始类型

2. 生命周期钩子最佳实践


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

export default {
    setup() {
        // 组合多个生命周期钩子
        onMounted(() => {
            console.log('组件挂载')
            initializeData()
        })

        onUpdated(() => {
            console.log('组件更新')
        })

        onUnmounted(() => {
            console.log('组件卸载')
            cleanup()
        })

        // 可以多次使用同一个钩子
        onMounted(() => {
            initializeOtherStuff()
        })
    }
}
                        

3. 组合式函数(Composables)

3.1 封装可复用逻辑


// useCounter.js
import { ref, computed } from 'vue'

export function useCounter(initialValue = 0) {
    const count = ref(initialValue)
    const double = computed(() => count.value * 2)

    function increment() {
        count.value++
    }

    function decrement() {
        count.value--
    }

    return {
        count,
        double,
        increment,
        decrement
    }
}

// 使用组合式函数
import { useCounter } from './composables/useCounter'

export default {
    setup() {
        const { count, double, increment } = useCounter(10)
        return { count, double, increment }
    }
}
                        

最佳实践

  • 组合式函数名以"use"开头
  • 返回一个包含响应式状态的对象
  • 保持功能单一,便于组合使用
  • 考虑清理工作(如事件监听器)

4. 性能优化技巧

4.1 computed vs watch


// computed - 用于派生状态
const fullName = computed(() => {
    return `${firstName.value} ${lastName.value}`
})

// watch - 用于副作用
watch(searchQuery, async (newValue) => {
    const result = await fetchSearchResults(newValue)
    searchResults.value = result
})

// watchEffect - 自动追踪依赖
watchEffect(() => {
    console.log(`当前计数: ${count.value}`)
    document.title = `计数: ${count.value}`
})
                        

4.2 避免不必要的重渲染


// 使用shallowRef优化大型数据
const bigData = shallowRef(new BigData())

// 使用v-memo优化列表渲染
{{ expensiveComputation(item) }}