Vue 3 状态管理深度解析:Pinia 架构设计与性能优化

本文深入探讨 Vue 3 状态管理的最佳实践,重点解析 Pinia 架构设计、状态持久化、性能优化和 TypeScript 集成,通过完整的企业级案例展示如何构建可维护、高性能的状态管理方案。

图片[1]-Vue 3 状态管理深度解析:Pinia 架构设计与性能优化实战

一、Pinia 架构设计与核心概念

1.1 现代化状态管理架构

<template>
  <div class="pinia-architecture">
    <!-- 应用头部 -->
    <AppHeader />
    
    <!-- 主内容区域 -->
    <main class="main-content">
      <!-- 用户信息面板 -->
      <UserProfilePanel />
      
      <!-- 购物车 -->
      <ShoppingCart />
      
      <!-- 产品列表 -->
      <ProductList />
    </main>
    
    <!-- 全局加载状态 -->
    <GlobalLoadingOverlay />
    
    <!-- 通知系统 -->
    <NotificationCenter />
  </div>
</template>

<script setup>
import AppHeader from './components/AppHeader.vue'
import UserProfilePanel from './components/UserProfilePanel.vue'
import ShoppingCart from './components/ShoppingCart.vue'
import ProductList from './components/ProductList.vue'
import GlobalLoadingOverlay from './components/GlobalLoadingOverlay.vue'
import NotificationCenter from './components/NotificationCenter.vue'

// 应用初始化逻辑
import { useAppStore } from '@/stores/app'
import { onMounted } from 'vue'

const appStore = useAppStore()

onMounted(() => {
  appStore.initializeApp()
})
</script>

<style scoped>
.pinia-architecture {
  min-height: 100vh;
  background: #f5f5f5;
}

.main-content {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 20px;
}
</style>

1.2 核心 Store 架构设计

// stores/types.ts - TypeScript 类型定义
export interface User {
  id: string
  email: string
  name: string
  avatar?: string
  preferences: UserPreferences
  createdAt: Date
  lastLoginAt: Date
}

export interface UserPreferences {
  theme: 'light' | 'dark'
  language: string
  notifications: boolean
}

export interface Product {
  id: string
  name: string
  description: string
  price: number
  originalPrice?: number
  images: string[]
  category: string
  inventory: number
  rating: number
  reviewCount: number
  tags: string[]
}

export interface CartItem {
  productId: string
  product: Product
  quantity: number
  addedAt: Date
}

export interface AppState {
  initialized: boolean
  loading: boolean
  error: string | null
  currentRoute: string
}

export interface Notification {
  id: string
  type: 'success' | 'error' | 'warning' | 'info'
  title: string
  message: string
  duration?: number
  createdAt: Date
}

二、企业级 Store 实现

2.1 用户状态管理 Store

// stores/userStore.ts
import { defineStore } from 'pinia'
import { ref, computed, watch } from 'vue'
import type { User, UserPreferences } from './types'

// API 服务
import { authApi, userApi } from '@/services/api'

export const useUserStore = defineStore('user', () => {
  // State
  const currentUser = ref<User | null>(null)
  const isLoading = ref(false)
  const error = ref<string | null>(null)
  const permissions = ref<string[]>([])

  // Getters
  const isLoggedIn = computed(() => !!currentUser.value)
  const userPreferences = computed(() => currentUser.value?.preferences)
  const hasPermission = computed(() => (permission: string) => 
    permissions.value.includes(permission)
  )

  // Actions
  const login = async (credentials: { email: string; password: string }) => {
    isLoading.value = true
    error.value = null
    
    try {
      const response = await authApi.login(credentials)
      currentUser.value = response.user
      permissions.value = response.permissions
      
      // 持久化用户信息
      localStorage.setItem('user_token', response.token)
      localStorage.setItem('user_data', JSON.stringify(response.user))
      
      return response
    } catch (err: any) {
      error.value = err.message
      throw err
    } finally {
      isLoading.value = false
    }
  }

  const logout = async () => {
    try {
      await authApi.logout()
    } catch (err) {
      console.error('Logout error:', err)
    } finally {
      // 清理本地状态
      currentUser.value = null
      permissions.value = []
      localStorage.removeItem('user_token')
      localStorage.removeItem('user_data')
    }
  }

  const updateProfile = async (profileData: Partial<User>) => {
    if (!currentUser.value) throw new Error('User not logged in')
    
    isLoading.value = true
    try {
      const updatedUser = await userApi.updateProfile(
        currentUser.value.id, 
        profileData
      )
      currentUser.value = { ...currentUser.value, ...updatedUser }
      return updatedUser
    } catch (err: any) {
      error.value = err.message
      throw err
    } finally {
      isLoading.value = false
    }
  }

  const updatePreferences = async (preferences: Partial<UserPreferences>) => {
    if (!currentUser.value) throw new Error('User not logged in')
    
    const newPreferences = { 
      ...currentUser.value.preferences, 
      ...preferences 
    }
    
    return updateProfile({ preferences: newPreferences })
  }

  // 初始化用户状态
  const initializeUser = () => {
    const savedUser = localStorage.getItem('user_data')
    const token = localStorage.getItem('user_token')
    
    if (savedUser && token) {
      try {
        currentUser.value = JSON.parse(savedUser)
        // 验证 token 有效性
        validateToken(token)
      } catch (err) {
        console.error('Failed to initialize user:', err)
        logout()
      }
    }
  }

  const validateToken = async (token: string) => {
    try {
      await authApi.validateToken(token)
    } catch (err) {
      console.error('Token validation failed:', err)
      logout()
    }
  }

  // 监听用户偏好变化
  watch(userPreferences, (newPreferences) => {
    if (newPreferences) {
      // 应用主题偏好
      document.documentElement.setAttribute(
        'data-theme', 
        newPreferences.theme
      )
      
      // 应用语言偏好
      document.documentElement.lang = newPreferences.language
    }
  }, { immediate: true })

  return {
    // State
    currentUser,
    isLoading,
    error,
    permissions,
    
    // Getters
    isLoggedIn,
    userPreferences,
    hasPermission,
    
    // Actions
    login,
    logout,
    updateProfile,
    updatePreferences,
    initializeUser
  }
})

2.2 购物车状态管理 Store

// stores/cartStore.ts
import { defineStore } from 'pinia'
import { ref, computed, watch } from 'vue'
import type { CartItem, Product } from './types'

export const useCartStore = defineStore('cart', () => {
  // State
  const items = ref<CartItem[]>([])
  const isOpen = ref(false)
  const isLoading = ref(false)

  // Getters
  const totalItems = computed(() => 
    items.value.reduce((sum, item) => sum + item.quantity, 0)
  )

  const totalPrice = computed(() =>
    items.value.reduce((sum, item) => 
      sum + (item.product.price * item.quantity), 0
    )
  )

  const discountedTotal = computed(() => {
    const total = totalPrice.value
    // 模拟折扣逻辑
    if (total > 100) return total * 0.9 // 10% 折扣
    return total
  })

  const isProductInCart = computed(() => (productId: string) =>
    items.value.some(item => item.productId === productId)
  )

  const getProductQuantity = computed(() => (productId: string) =>
    items.value.find(item => item.productId === productId)?.quantity || 0
  )

  // Actions
  const addToCart = (product: Product, quantity: number = 1) => {
    const existingItem = items.value.find(
      item => item.productId === product.id
    )

    if (existingItem) {
      // 更新现有商品数量
      existingItem.quantity += quantity
    } else {
      // 添加新商品
      items.value.push({
        productId: product.id,
        product,
        quantity,
        addedAt: new Date()
      })
    }

    // 自动打开购物车
    if (!isOpen.value) {
      isOpen.value = true
    }
  }

  const removeFromCart = (productId: string) => {
    const index = items.value.findIndex(item => item.productId === productId)
    if (index !== -1) {
      items.value.splice(index, 1)
    }
  }

  const updateQuantity = (productId: string, quantity: number) => {
    const item = items.value.find(item => item.productId === productId)
    if (item) {
      if (quantity <= 0) {
        removeFromCart(productId)
      } else {
        item.quantity = quantity
      }
    }
  }

  const clearCart = () => {
    items.value = []
  }

  const toggleCart = () => {
    isOpen.value = !isOpen.value
  }

  // 持久化购物车状态
  const CART_STORAGE_KEY = 'shopping_cart'

  const saveCartToStorage = () => {
    const cartData = {
      items: items.value,
      savedAt: new Date().toISOString()
    }
    localStorage.setItem(CART_STORAGE_KEY, JSON.stringify(cartData))
  }

  const loadCartFromStorage = () => {
    try {
      const saved = localStorage.getItem(CART_STORAGE_KEY)
      if (saved) {
        const cartData = JSON.parse(saved)
        // 可以在这里添加数据验证和迁移逻辑
        items.value = cartData.items.map((item: any) => ({
          ...item,
          addedAt: new Date(item.addedAt)
        }))
      }
    } catch (err) {
      console.error('Failed to load cart from storage:', err)
      clearCart()
    }
  }

  // 自动保存到 localStorage
  watch(items, saveCartToStorage, { deep: true })

  return {
    // State
    items,
    isOpen,
    isLoading,
    
    // Getters
    totalItems,
    totalPrice,
    discountedTotal,
    isProductInCart,
    getProductQuantity,
    
    // Actions
    addToCart,
    removeFromCart,
    updateQuantity,
    clearCart,
    toggleCart,
    loadCartFromStorage
  }
})

三、高级状态管理模式

3.1 应用状态管理 Store

// stores/appStore.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { Notification, AppState } from './types'

export const useAppStore = defineStore('app', () => {
  // State
  const state = ref<AppState>({
    initialized: false,
    loading: false,
    error: null,
    currentRoute: '/'
  })

  const notifications = ref<Notification[]>([])
  const pendingRequests = ref<number>(0)

  // Getters
  const isLoading = computed(() => state.value.loading)
  const hasError = computed(() => !!state.value.error)
  const isInitialized = computed(() => state.value.initialized)
  const unreadNotifications = computed(() => 
    notifications.value.filter(n => !n.read)
  )

  // Actions
  const setLoading = (loading: boolean) => {
    state.value.loading = loading
  }

  const setError = (error: string | null) => {
    state.value.error = error
  }

  const setCurrentRoute = (route: string) => {
    state.value.currentRoute = route
  }

  const addNotification = (notification: Omit<Notification, 'id' | 'createdAt'>) => {
    const newNotification: Notification = {
      ...notification,
      id: generateId(),
      createdAt: new Date()
    }

    notifications.value.push(newNotification)

    // 自动移除通知
    if (newNotification.duration && newNotification.duration > 0) {
      setTimeout(() => {
        removeNotification(newNotification.id)
      }, newNotification.duration)
    }
  }

  const removeNotification = (id: string) => {
    const index = notifications.value.findIndex(n => n.id === id)
    if (index !== -1) {
      notifications.value.splice(index, 1)
    }
  }

  const clearNotifications = () => {
    notifications.value = []
  }

  // 请求计数器
  const startRequest = () => {
    pendingRequests.value++
    if (pendingRequests.value === 1) {
      setLoading(true)
    }
  }

  const endRequest = () => {
    pendingRequests.value = Math.max(0, pendingRequests.value - 1)
    if (pendingRequests.value === 0) {
      setLoading(false)
    }
  }

  // 应用初始化
  const initializeApp = async () => {
    if (state.value.initialized) return

    startRequest()
    try {
      // 初始化各个 store
      const userStore = useUserStore()
      const cartStore = useCartStore()

      await Promise.all([
        userStore.initializeUser(),
        cartStore.loadCartFromStorage()
      ])

      state.value.initialized = true
      addNotification({
        type: 'success',
        title: '应用就绪',
        message: '应用初始化完成',
        duration: 3000
      })
    } catch (error: any) {
      setError(`初始化失败: ${error.message}`)
      addNotification({
        type: 'error',
        title: '初始化错误',
        message: '应用初始化过程中发生错误'
      })
    } finally {
      endRequest()
    }
  }

  // 工具函数
  const generateId = (): string => {
    return Date.now().toString(36) + Math.random().toString(36).substr(2)
  }

  return {
    // State
    state,
    notifications,
    pendingRequests,
    
    // Getters
    isLoading,
    hasError,
    isInitialized,
    unreadNotifications,
    
    // Actions
    setLoading,
    setError,
    setCurrentRoute,
    addNotification,
    removeNotification,
    clearNotifications,
    startRequest,
    endRequest,
    initializeApp
  }
})

3.2 Store 组合与模块化

// stores/index.ts - Store 聚合和初始化
import { createPinia } from 'pinia'
import { markRaw } from 'vue'
import type { Router } from 'vue-router'

// Pinia 插件示例
const persistencePlugin = ({ store }: any) => {
  // 从 localStorage 恢复状态
  const saved = localStorage.getItem(`pinia_${store.$id}`)
  if (saved) {
    store.$patch(JSON.parse(saved))
  }

  // 监听变化并保存
  store.$subscribe((mutation: any, state: any) => {
    localStorage.setItem(`pinia_${store.$id}`, JSON.stringify(state))
  })
}

const routerPlugin = (router: Router) => ({ store }: any) => {
  store.router = markRaw(router)
}

export const setupStores = (router: Router) => {
  const pinia = createPinia()
  
  // 注册插件
  pinia.use(persistencePlugin)
  pinia.use(routerPlugin(router))
  
  return pinia
}

// Store 组合函数
export const useStores = () => {
  return {
    app: useAppStore(),
    user: useUserStore(),
    cart: useCartStore(),
    products: useProductStore()
  }
}

// 类型安全的 store 访问
export type AppStores = ReturnType<typeof useStores>

四、组件集成与性能优化

4.1 组件集成示例

<!-- components/ShoppingCart.vue -->
<template>
  <div class="shopping-cart" :class="{ 'cart-open': isOpen }">
    <!-- 购物车遮罩 -->
    <div v-if="isOpen" class="cart-overlay" @click="toggleCart"></div>
    
    <!-- 购物车侧边栏 -->
    <aside class="cart-sidebar">
      <div class="cart-header">
        <h3>购物车 ({{ totalItems }})</h3>
        <button @click="toggleCart" class="close-btn">×</button>
      </div>
      
      <div class="cart-content">
        <!-- 空状态 -->
        <div v-if="items.length === 0" class="empty-cart">
          <p>购物车是空的</p>
          <button @click="toggleCart" class="btn btn-primary">
            继续购物
          </button>
        </div>
        
        <!-- 商品列表 -->
        <div v-else class="cart-items">
          <CartItem
            v-for="item in items"
            :key="item.productId"
            :item="item"
            @update-quantity="updateQuantity"
            @remove="removeFromCart"
          />
        </div>
      </div>
      
      <!-- 购物车底部 -->
      <div v-if="items.length > 0" class="cart-footer">
        <div class="cart-summary">
          <div class="summary-row">
            <span>小计:</span>
            <span>¥{{ totalPrice.toFixed(2) }}</span>
          </div>
          <div v-if="discountedTotal < totalPrice" class="summary-row discount">
            <span>折扣:</span>
            <span>-¥{{ (totalPrice - discountedTotal).toFixed(2) }}</span>
          </div>
          <div class="summary-row total">
            <span>总计:</span>
            <span>¥{{ discountedTotal.toFixed(2) }}</span>
          </div>
        </div>
        
        <button class="checkout-btn" @click="proceedToCheckout">
          结算
        </button>
      </div>
    </aside>
  </div>
</template>

<script setup lang="ts">
import { storeToRefs } from 'pinia'
import { useCartStore } from '@/stores/cartStore'
import CartItem from './CartItem.vue'

const cartStore = useCartStore()

// 使用 storeToRefs 保持响应式
const { 
  items, 
  isOpen, 
  totalItems, 
  totalPrice, 
  discountedTotal 
} = storeToRefs(cartStore)

const { 
  toggleCart, 
  updateQuantity, 
  removeFromCart 
} = cartStore

const proceedToCheckout = () => {
  // 结算逻辑
  console.log('Proceeding to checkout...')
  toggleCart()
}
</script>

<style scoped>
.shopping-cart {
  position: relative;
}

.cart-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 100;
}

.cart-sidebar {
  position: fixed;
  top: 0;
  right: -400px;
  width: 400px;
  height: 100vh;
  background: white;
  box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1);
  transition: right 0.3s ease;
  z-index: 101;
  display: flex;
  flex-direction: column;
}

.cart-open .cart-sidebar {
  right: 0;
}

.cart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  border-bottom: 1px solid #e5e5e5;
}

.close-btn {
  background: none;
  border: none;
  font-size: 24px;
  cursor: pointer;
  padding: 0;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.cart-content {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}

.empty-cart {
  text-align: center;
  padding: 40px 20px;
}

.cart-footer {
  border-top: 1px solid #e5e5e5;
  padding: 20px;
}

.cart-summary {
  margin-bottom: 20px;
}

.summary-row {
  display: flex;
  justify-content: space-between;
  margin-bottom: 8px;
}

.summary-row.discount {
  color: #10b981;
}

.summary-row.total {
  font-weight: bold;
  font-size: 1.1em;
  border-top: 1px solid #e5e5e5;
  padding-top: 8px;
}

.checkout-btn {
  width: 100%;
  padding: 12px;
  background: #3b82f6;
  color: white;
  border: none;
  border-radius: 6px;
  font-size: 16px;
  cursor: pointer;
  transition: background 0.2s;
}

.checkout-btn:hover {
  background: #2563eb;
}
</style>

4.2 性能优化组件

<!-- components/ProductList.vue -->
<template>
  <div class="product-list">
    <!-- 筛选控件 -->
    <div class="filters">
      <input
        v-model="searchQuery"
        placeholder="搜索商品..."
        class="search-input"
        @input="handleSearch"
      />
      
      <select v-model="selectedCategory" @change="handleFilter" class="category-select">
        <option value="">所有分类</option>
        <option v-for="category in categories" :key="category" :value="category">
          {{ category }}
        </option>
      </select>
    </div>

    <!-- 加载状态 -->
    <div v-if="isLoading" class="loading">
      加载中...
    </div>

    <!-- 商品网格 -->
    <div v-else class="products-grid">
      <ProductCard
        v-for="product in paginatedProducts"
        :key="product.id"
        :product="product"
        @add-to-cart="handleAddToCart"
      />
    </div>

    <!-- 分页控件 -->
    <div v-if="totalPages > 1" class="pagination">
      <button 
        :disabled="currentPage === 1" 
        @click="prevPage"
        class="pagination-btn"
      >
        上一页
      </button>
      
      <span class="page-info">
        第 {{ currentPage }} 页,共 {{ totalPages }} 页
      </span>
      
      <button 
        :disabled="currentPage === totalPages" 
        @click="nextPage"
        class="pagination-btn"
      >
        下一页
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch, onMounted } from 'vue'
import { storeToRefs } from 'pinia'
import { useProductStore } from '@/stores/productStore'
import { useCartStore } from '@/stores/cartStore'
import ProductCard from './ProductCard.vue'

// Store
const productStore = useProductStore()
const cartStore = useCartStore()

const { 
  products, 
  categories, 
  isLoading 
} = storeToRefs(productStore)

const { loadProducts } = productStore
const { addToCart } = cartStore

// 本地状态
const searchQuery = ref('')
const selectedCategory = ref('')
const currentPage = ref(1)
const itemsPerPage = 12

// 计算属性
const filteredProducts = computed(() => {
  let filtered = products.value

  // 搜索过滤
  if (searchQuery.value) {
    const query = searchQuery.value.toLowerCase()
    filtered = filtered.filter(product =>
      product.name.toLowerCase().includes(query) ||
      product.description.toLowerCase().includes(query)
    )
  }

  // 分类过滤
  if (selectedCategory.value) {
    filtered = filtered.filter(product => 
      product.category === selectedCategory.value
    )
  }

  return filtered
})

const totalPages = computed(() => 
  Math.ceil(filteredProducts.value.length / itemsPerPage)
)

const paginatedProducts = computed(() => {
  const start = (currentPage.value - 1) * itemsPerPage
  const end = start + itemsPerPage
  return filteredProducts.value.slice(start, end)
})

// 方法
const handleSearch = () => {
  currentPage.value = 1 // 重置到第一页
}

const handleFilter = () => {
  currentPage.value = 1 // 重置到第一页
}

const handleAddToCart = (product: any) => {
  addToCart(product, 1)
}

const prevPage = () => {
  if (currentPage.value > 1) {
    currentPage.value--
  }
}

const nextPage = () => {
  if (currentPage.value < totalPages.value) {
    currentPage.value++
  }
}

// 监听筛选条件变化
watch([searchQuery, selectedCategory], () => {
  currentPage.value = 1
})

// 生命周期
onMounted(() => {
  loadProducts()
})
</script>

<style scoped>
.product-list {
  padding: 20px;
}

.filters {
  display: flex;
  gap: 15px;
  margin-bottom: 20px;
  align-items: center;
}

.search-input {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 14px;
}

.category-select {
  padding: 8px 12px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  background: white;
  min-width: 150px;
}

.products-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
  margin-bottom: 30px;
}

.loading {
  text-align: center;
  padding: 40px;
  color: #6b7280;
}

.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 15px;
  margin-top: 30px;
}

.pagination-btn {
  padding: 8px 16px;
  border: 1px solid #d1d5db;
  background: white;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s;
}

.pagination-btn:hover:not(:disabled) {
  background: #f3f4f6;
}

.pagination-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.page-info {
  color: #6b7280;
  font-size: 14px;
}
</style>

五、高级模式与最佳实践

5.1 Store 测试策略

// tests/unit/userStore.spec.ts
import { setActivePinia, createPinia } from 'pinia'
import { useUserStore } from '@/stores/userStore'
import { describe, it, expect, beforeEach, vi } from 'vitest'

// Mock API
vi.mock('@/services/api', () => ({
  authApi: {
    login: vi.fn(),
    logout: vi.fn(),
    validateToken: vi.fn()
  },
  userApi: {
    updateProfile: vi.fn()
  }
}))

describe('User Store', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    localStorage.clear()
  })

  it('should initialize with null user', () => {
    const store = useUserStore()
    expect(store.currentUser).toBeNull()
    expect(store.isLoggedIn).toBe(false)
  })

  it('should handle successful login', async () => {
    const store = useUserStore()
    const mockUser = {
      id: '1',
      email: 'test@example.com',
      name: 'Test User'
    }

    // Mock API response
    const { authApi } = await import('@/services/api')
    vi.mocked(authApi.login).mockResolvedValue({
      user: mockUser,
      token: 'fake-token',
      permissions: ['read', 'write']
    })

    await store.login({
      email: 'test@example.com',
      password: 'password'
    })

    expect(store.currentUser).toEqual(mockUser)
    expect(store.isLoggedIn).toBe(true)
    expect(localStorage.getItem('user_token')).toBe('fake-token')
  })

  it('should handle login failure', async () => {
    const store = useUserStore()

    const { authApi } = await import('@/services/api')
    vi.mocked(authApi.login).mockRejectedValue(
      new Error('Invalid credentials')
    )

    await expect(
      store.login({
        email: 'test@example.com',
        password: 'wrong'
      })
    ).rejects.toThrow('Invalid credentials')

    expect(store.currentUser).toBeNull()
    expect(store.error).toBe('Invalid credentials')
  })
})

5.2 性能优化配置

// stores/performance.ts
import { watch, nextTick } from 'vue'

// 防抖操作
export const useDebouncedFn = <T extends (...args: any[]) => any>(
  fn: T,
  delay: number
) => {
  let timeoutId: number | null = null
  
  return (...args: Parameters<T>): void => {
    if (timeoutId) {
      clearTimeout(timeoutId)
    }
    
    timeoutId = window.setTimeout(() => {
      fn(...args)
    }, delay)
  }
}

// 批量更新
export const useBatchUpdates = (callback: () => void) => {
  let scheduled = false
  
  const scheduleUpdate = () => {
    if (!scheduled) {
      scheduled = true
      nextTick(() => {
        scheduled = false
        callback()
      })
    }
  }
  
  return scheduleUpdate
}

// Store 性能监控
export const useStorePerformance = (store: any) => {
  watch(
    () => store.$state,
    (newState, oldState) => {
      // 可以在这里添加性能监控逻辑
      console.log('Store state changed:', store.$id)
    },
    { deep: true, flush: 'post' }
  )
}

通过这种架构设计,我们构建了一个可维护、可测试、高性能的 Vue 3 状态管理系统,能够支撑复杂的企业级应用需求。


© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容