Skip to content
On this page

Pinia 开发者工具 (DevTools)

Vue DevTools 为 Pinia 提供了强大的调试功能,可以监控 Store 状态变化、时间旅行调试、性能分析等。本指南将详细介绍如何使用和配置 DevTools 与 Pinia 集成。

安装和配置 DevTools

安装 Vue DevTools

浏览器扩展

作为独立应用

bash
npm install -g @vue/devtools
# 然后运行
npx @vue/devtools

基本集成

通常情况下,Pinia 会自动与 Vue DevTools 集成,无需额外配置:

javascript
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
const pinia = createPinia()

app.use(pinia)
app.mount('#app')

DevTools 功能详解

1. Store 检查

在 DevTools 的 Pinia 面板中,您可以:

  • 查看所有 Store 实例
  • 检查当前状态值
  • 查看 Getters 的计算结果
  • 监控 Actions 的执行
javascript
// 示例 Store
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    name: 'My Counter',
  }),
  
  getters: {
    doubleCount: (state) => state.count * 2,
    tripleCount: (state) => state.count * 3,
  },
  
  actions: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    },
    incrementAsync() {
      return new Promise((resolve) => {
        setTimeout(() => {
          this.increment()
          resolve()
        }, 1000)
      })
    },
  },
})

2. 状态修改

在 DevTools 中可以直接修改状态值:

  • 点击状态值进行编辑
  • 直接输入新值
  • 支持基本数据类型和简单对象

3. 时间旅行调试

可以回退到之前的状态:

  • 查看状态变化历史
  • 回退到特定状态
  • 重放特定操作

高级 DevTools 配置

自定义 DevTools 显示

javascript
import { defineStore } from 'pinia'

export const useCustomDisplayStore = defineStore('custom-display', {
  state: () => ({
    users: [
      { id: 1, name: 'Alice', role: 'admin' },
      { id: 2, name: 'Bob', role: 'user' },
    ],
    loading: false,
    error: null,
  }),
  
  getters: {
    adminUsers: (state) => state.users.filter(user => user.role === 'admin'),
    userCount: (state) => state.users.length,
  },
  
  actions: {
    async fetchUsers() {
      this.loading = true
      try {
        // 模拟 API 调用
        await new Promise(resolve => setTimeout(resolve, 1000))
        this.loading = false
      } catch (error) {
        this.error = error.message
        this.loading = false
      }
    },
  },
  
  // 自定义 DevTools 显示
  $devtools: {
    // 自定义显示的属性
    displayName: 'User Management',
    // 自定义工具提示
    tooltip: 'Manages application users',
  },
})

添加自定义属性到 DevTools

javascript
const devtoolsPlugin = ({ store }) => {
  // 为所有 Store 添加调试信息
  store._customProperties = store._customProperties || new Set()
  store._customProperties.add('debugInfo')
  
  // 添加计算属性到 DevTools
  store.$patch({
    debugInfo: {
      createdAt: Date.now(),
      lastAccessed: null,
    },
  })
  
  // 监听 Store 操作
  store.$subscribe((mutation, state) => {
    store.debugInfo.lastAccessed = Date.now()
  })
}

// 应用插件
const pinia = createPinia()
pinia.use(devtoolsPlugin)

DevTools 插件开发

创建自定义 DevTools 插件

javascript
// devtools-plugin.js
export const createDevToolsPlugin = (options = {}) => {
  return (context) => {
    const { store, pinia } = context
    
    // 仅在开发环境中启用
    if (process.env.NODE_ENV === 'development') {
      // 添加自定义调试信息
      store._customProperties = store._customProperties || new Set()
      
      // 添加性能指标
      store.performance = {
        actionCount: 0,
        mutationCount: 0,
      }
      
      // 监听 Actions
      const originalAction = store.$onAction
      store.$onAction((context) => {
        store.performance.actionCount++
        
        context.after(() => {
          // Action 完成后的逻辑
        })
        
        context.onSuccess(() => {
          // Action 成功后的逻辑
        })
        
        context.onError(() => {
          // Action 失败后的逻辑
        })
      })
    }
  }
}

性能监控

监控 Store 性能

javascript
const performancePlugin = ({ store }) => {
  if (process.env.NODE_ENV === 'development') {
    // 添加性能监控
    const originalAction = store.$onAction
    
    store.$onAction((context) => {
      const startTime = performance.now()
      
      context.after(() => {
        const endTime = performance.now()
        const duration = endTime - startTime
        
        if (duration > 100) { // 超过 100ms 的操作
          console.warn(`[Performance] ${store.$id}.${context.name} took ${duration}ms`)
        }
      })
    })
  }
}

const pinia = createPinia()
pinia.use(performancePlugin)

调试技巧

1. 状态快照

javascript
// 在控制台中获取状态快照
const store = useCounterStore()
console.log('Current state:', JSON.parse(JSON.stringify(store.$state)))

2. 操作追踪

javascript
// 追踪特定操作
export const useTrackedStore = defineStore('tracked', {
  state: () => ({
    data: [],
  }),
  
  actions: {
    async loadData() {
      console.group('loadData action started') // DevTools 中的分组
      try {
        const result = await fetch('/api/data')
        this.data = await result.json()
        console.log('Data loaded successfully', this.data)
      } catch (error) {
        console.error('Failed to load data', error)
        throw error
      } finally {
        console.groupEnd() // 结束分组
      }
    },
  },
})

3. 状态验证

javascript
const validationPlugin = ({ store }) => {
  // 添加状态验证
  store.$subscribe((mutation, state) => {
    // 验证状态的一致性
    if (store.$id === 'user' && state.profile) {
      if (!state.profile.id || !state.profile.name) {
        console.warn(`[Validation] User profile is incomplete:`, state.profile)
      }
    }
  })
}

const pinia = createPinia()
pinia.use(validationPlugin)

生产环境配置

有条件地启用 DevTools

javascript
// stores/index.js
import { createPinia } from 'pinia'

export const configurePinia = () => {
  const pinia = createPinia()
  
  // 仅在开发环境中启用额外的 DevTools 功能
  if (process.env.NODE_ENV === 'development') {
    // 开发环境专用插件
    pinia.use(devtoolsEnhancementPlugin)
  }
  
  return pinia
}

const devtoolsEnhancementPlugin = ({ store }) => {
  // 添加开发环境专用的调试功能
  store._debug = {
    createdAt: Date.now(),
    accessedProperties: new Set(),
  }
  
  // 拦截属性访问
  for (const key of Object.keys(store)) {
    if (typeof store[key] !== 'function') {
      Object.defineProperty(store, key, {
        get() {
          store._debug.accessedProperties.add(key)
          return store._state.value[key]
        },
        set(value) {
          store._state.value[key] = value
        },
        enumerable: true,
        configurable: true,
      })
    }
  }
}

常见问题和解决方案

1. DevTools 不显示 Store

可能原因和解决方案:

  • 确保 Pinia 实例已正确安装到 Vue 应用
  • 检查是否在开发模式下运行
  • 确认 DevTools 扩展已启用

2. 状态无法正确显示

javascript
// 确保状态是可序列化的
export const useValidStore = defineStore('valid', {
  state: () => ({
    // 好的做法:使用基本数据类型和普通对象
    count: 0,
    user: { name: 'John', age: 30 },
    tags: ['vue', 'pinia'],
    
    // 避免:使用函数、DOM 元素等不可序列化对象
    // callback: () => {}, // 不要这样做
    // element: document.body, // 不要这样做
  }),
})

3. 性能问题

javascript
// 对于大数据量的 Store,考虑部分监控
export const useLargeDataStore = defineStore('large-data', {
  state: () => ({
    items: new Array(10000).fill(0).map((_, i) => ({ id: i, value: i })),
  }),
  
  persist: {
    // 只持久化必要的部分
    pick: ['importantData'],
  },
  
  actions: {
    updateItem(id, newValue) {
      // 使用索引直接更新,而不是重新分配整个数组
      const index = this.items.findIndex(item => item.id === id)
      if (index !== -1) {
        this.items[index].value = newValue
      }
    },
  },
})

通过合理使用 DevTools,您可以更有效地调试和优化 Pinia 应用,提高开发效率和应用质量。