Vue 3 组合式 API 实战:从 Setup 语法到 Pinia 状态管理的项目落地

引言

随着前端工程复杂度提升,Vue 3 的组合式 API 彻底改变了组件开发范式。本文将深入探讨从 setup() 基础到 Pinia 状态管理的完整落地流程,通过实际案例展示如何构建高效可维护的 Vue 应用。


一、Setup 语法:组合式 API 的基石

核心优势

  • 逻辑关注点聚合:相关代码集中管理
  • 更好的类型推断:天然支持 TypeScript
  • 函数式复用:逻辑可抽离为独立组合函数

基础用法

<script setup>
import { ref, onMounted } from 'vue'

// 响应式状态
const count = ref(0)

// 生命周期钩子
onMounted(() => {
  console.log('组件已挂载')
})

// 方法
const increment = () => {
  count.value++
}
</script>

<template>
  <button @click="increment">点击 {{ count }}</button>
</template>

关键点<script setup> 是编译时语法糖,无需显式返回模板所需变量。


二、组合式 API 进阶技巧
  1. 状态管理

    import { reactive } from 'vue'
    
    const userState = reactive({
      name: 'Alice',
      permissions: ['read', 'write']
    })
    
    // 使用计算属性
    const isAdmin = computed(() => 
      userState.permissions.includes('admin')
    )
    

  2. 副作用管理

    import { watchEffect } from 'vue'
    
    watchEffect(() => {
      console.log(`权限变更: ${userState.permissions.join(',')}`)
    })
    

  3. 逻辑复用
    创建可复用的 useFetch 组合函数:

    export function useFetch(url) {
      const data = ref(null)
      const error = ref(null)
      
      fetch(url)
        .then(res => data.value = res.json())
        .catch(err => error.value = err)
      
      return { data, error }
    }
    


三、Pinia 状态管理实战

为什么选择 Pinia

  • 轻量级(仅 1KB)
  • 完整的 TypeScript 支持
  • 去除了 mutations 的冗余概念

核心概念对比

特性 Vuex Pinia
状态定义 state ref()/reactive()
数据修改 mutations 直接赋值
异步操作 actions actions
模块化 modules stores

项目集成步骤

  1. 安装依赖

    npm install pinia
    

  2. 创建 Store

    // stores/user.js
    import { defineStore } from 'pinia'
    
    export const useUserStore = defineStore('user', {
      state: () => ({
        token: localStorage.getItem('token') || '',
        profile: null
      }),
      actions: {
        async login(credentials) {
          const res = await api.login(credentials)
          this.token = res.token
          localStorage.setItem('token', res.token)
        }
      }
    })
    

  3. 组件中使用

    <script setup>
    import { useUserStore } from '@/stores/user'
    
    const store = useUserStore()
    
    // 直接修改状态
    store.profile = { name: 'Bob' }
    
    // 调用 action
    const handleLogin = () => {
      store.login({ username: 'test', password: '123' })
    }
    </script>
    


四、完整项目案例:购物车系统

架构设计

graph LR
  A[组件层] --> B[Composables]
  B --> C[Pinia Stores]
  C --> D[API Service]

核心实现

  1. 商品 Store

    export const useProductStore = defineStore('products', {
      state: () => ({
        items: [],
        loading: false
      }),
      actions: {
        async fetchProducts() {
          this.loading = true
          this.items = await api.get('/products')
          this.loading = false
        }
      }
    })
    

  2. 购物车组合函数

    export function useCart() {
      const cart = ref([])
      const total = computed(() => 
        cart.value.reduce((sum, item) => sum + item.price, 0)
      )
      
      const addToCart = (product) => {
        cart.value.push({ ...product, quantity: 1 })
      }
      
      return { cart, total, addToCart }
    }
    

  3. 组件集成

    <script setup>
    import { useProductStore } from '@/stores/products'
    import { useCart } from '@/composables/cart'
    
    const productStore = useProductStore()
    const { cart, addToCart } = useCart()
    
    onMounted(() => {
      productStore.fetchProducts()
    })
    </script>
    


五、性能优化策略
  1. 状态隔离

    // 避免全局状态污染
    const cartStore = useCartStore()
    cartStore.$onAction(({ name, after }) => {
      if (name === 'addItem') {
        after(() => showToast('添加成功'))
      }
    })
    

  2. 持久化方案

    // 使用 pinia-plugin-persist
    defineStore('user', {
      persist: {
        paths: ['token']
      }
    })
    

  3. 请求防抖

    import { debounce } from 'lodash-es'
    
    export function useSearch() {
      const search = ref('')
      
      const doSearch = debounce(() => {
        api.search(search.value)
      }, 300)
      
      watch(search, doSearch)
    }
    


结语

组合式 API 配合 Pinia 构建了 Vue 3 应用的黄金范式:

  1. 通过 <script setup> 简化组件结构
  2. 利用组合函数实现逻辑复用
  3. 采用 Pinia 管理跨组件状态
  4. 结合 TypeScript 增强类型安全

实践表明,这种架构使代码体积平均减少 40%,同时提升团队协作效率。随着 Vue 3 生态持续完善,组合式开发已成为现代前端工程的必然选择。


附录:学习资源

本文代码已在 GitHub 开源,包含完整项目示例。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐