1. 性能监控

1.1 性能指标监控

// utils/performance.js
class PerformanceMonitor {
  constructor() {
    this.metrics = {
      pageLoadTime: 0,
      firstPaint: 0,
      firstContentfulPaint: 0,
      largestContentfulPaint: 0,
      memoryUsage: 0,
      networkRequests: [],
      errors: []
    }
    
    this.observers = []
    this.init()
  }
  
  // 初始化性能监控
  init() {
    this.monitorPageLoad()
    this.monitorMemory()
    this.monitorNetwork()
    this.monitorErrors()
    
    // #ifdef H5
    this.monitorWebVitals()
    // #endif
  }
  
  // 监控页面加载时间
  monitorPageLoad() {
    const startTime = Date.now()
    
    // 页面加载完成时记录
    uni.$on('pageReady', () => {
      this.metrics.pageLoadTime = Date.now() - startTime
      this.reportMetric('pageLoadTime', this.metrics.pageLoadTime)
    })
  }
  
  // 监控内存使用
  monitorMemory() {
    // #ifdef H5
    if (performance.memory) {
      setInterval(() => {
        this.metrics.memoryUsage = {
          used: performance.memory.usedJSHeapSize,
          total: performance.memory.totalJSHeapSize,
          limit: performance.memory.jsHeapSizeLimit
        }
        
        // 内存使用率超过80%时警告
        const usageRate = this.metrics.memoryUsage.used / this.metrics.memoryUsage.total
        if (usageRate > 0.8) {
          console.warn('内存使用率过高:', usageRate)
          this.reportMetric('highMemoryUsage', usageRate)
        }
      }, 5000)
    }
    // #endif
    
    // #ifdef APP-PLUS
    setInterval(() => {
      plus.runtime.getProperty(plus.runtime.appid, (info) => {
        this.metrics.memoryUsage = {
          used: info.memory || 0
        }
      })
    }, 5000)
    // #endif
  }
  
  // 监控网络请求
  monitorNetwork() {
    const originalRequest = uni.request
    
    uni.request = (options) => {
      const startTime = Date.now()
      const requestInfo = {
        url: options.url,
        method: options.method || 'GET',
        startTime,
        endTime: 0,
        duration: 0,
        success: false,
        statusCode: 0,
        size: 0
      }
      
      const originalSuccess = options.success
      const originalFail = options.fail
      const originalComplete = options.complete
      
      options.success = (res) => {
        requestInfo.endTime = Date.now()
        requestInfo.duration = requestInfo.endTime - requestInfo.startTime
        requestInfo.success = true
        requestInfo.statusCode = res.statusCode
        requestInfo.size = JSON.stringify(res.data).length
        
        this.metrics.networkRequests.push(requestInfo)
        
        // 慢请求警告(超过3秒)
        if (requestInfo.duration > 3000) {
          console.warn('慢请求检测:', requestInfo)
          this.reportMetric('slowRequest', requestInfo)
        }
        
        if (originalSuccess) originalSuccess(res)
      }
      
      options.fail = (err) => {
        requestInfo.endTime = Date.now()
        requestInfo.duration = requestInfo.endTime - requestInfo.startTime
        requestInfo.success = false
        requestInfo.error = err
        
        this.metrics.networkRequests.push(requestInfo)
        this.reportMetric('requestError', requestInfo)
        
        if (originalFail) originalFail(err)
      }
      
      options.complete = (res) => {
        // 保持网络请求记录在合理范围内
        if (this.metrics.networkRequests.length > 100) {
          this.metrics.networkRequests = this.metrics.networkRequests.slice(-50)
        }
        
        if (originalComplete) originalComplete(res)
      }
      
      return originalRequest(options)
    }
  }
  
  // 监控错误
  monitorErrors() {
    // Vue错误处理
    const app = getApp()
    if (app && app.globalData && app.globalData.Vue) {
      app.globalData.Vue.config.errorHandler = (err, vm, info) => {
        const errorInfo = {
          type: 'vue',
          message: err.message,
          stack: err.stack,
          info,
          timestamp: Date.now(),
          url: getCurrentPages().pop()?.route || 'unknown'
        }
        
        this.metrics.errors.push(errorInfo)
        this.reportMetric('error', errorInfo)
        
        console.error('Vue错误:', errorInfo)
      }
    }
    
    // Promise错误处理
    // #ifdef H5
    window.addEventListener('unhandledrejection', (event) => {
      const errorInfo = {
        type: 'promise',
        message: event.reason?.message || event.reason,
        stack: event.reason?.stack,
        timestamp: Date.now(),
        url: window.location.href
      }
      
      this.metrics.errors.push(errorInfo)
      this.reportMetric('error', errorInfo)
      
      console.error('Promise错误:', errorInfo)
    })
    // #endif
  }
  
  // 监控Web Vitals(H5专用)
  monitorWebVitals() {
    // #ifdef H5
    if (typeof PerformanceObserver !== 'undefined') {
      // First Paint
      const paintObserver = new PerformanceObserver((list) => {
        for (const entry of list.getEntries()) {
          if (entry.name === 'first-paint') {
            this.metrics.firstPaint = entry.startTime
          } else if (entry.name === 'first-contentful-paint') {
            this.metrics.firstContentfulPaint = entry.startTime
          }
        }
      })
      paintObserver.observe({ entryTypes: ['paint'] })
      
      // Largest Contentful Paint
      const lcpObserver = new PerformanceObserver((list) => {
        const entries = list.getEntries()
        const lastEntry = entries[entries.length - 1]
        this.metrics.largestContentfulPaint = lastEntry.startTime
      })
      lcpObserver.observe({ entryTypes: ['largest-contentful-paint'] })
      
      this.observers.push(paintObserver, lcpObserver)
    }
    // #endif
  }
  
  // 上报性能指标
  reportMetric(type, data) {
    // 这里可以上报到性能监控平台
    console.log(`性能指标 [${type}]:`, data)
    
    // 示例:上报到自定义服务器
    // uni.request({
    //   url: 'https://api.example.com/metrics',
    //   method: 'POST',
    //   data: {
    //     type,
    //     data,
    //     timestamp: Date.now(),
    //     userAgent: navigator.userAgent,
    //     appVersion: getApp().globalData.version
    //   }
    // })
  }
  
  // 获取性能报告
  getPerformanceReport() {
    const report = {
      ...this.metrics,
      timestamp: Date.now(),
      deviceInfo: uni.getSystemInfoSync()
    }
    
    // 计算网络请求统计
    const requests = this.metrics.networkRequests
    if (requests.length > 0) {
      report.networkStats = {
        total: requests.length,
        success: requests.filter(r => r.success).length,
        failed: requests.filter(r => !r.success).length,
        averageDuration: requests.reduce((sum, r) => sum + r.duration, 0) / requests.length,
        slowRequests: requests.filter(r => r.duration > 3000).length
      }
    }
    
    return report
  }
  
  // 清理监控器
  destroy() {
    this.observers.forEach(observer => {
      if (observer.disconnect) {
        observer.disconnect()
      }
    })
    this.observers = []
  }
}

// 创建性能监控实例
const performanceMonitor = new PerformanceMonitor()

export default performanceMonitor

1.2 FPS监控

// utils/fpsMonitor.js
class FPSMonitor {
  constructor() {
    this.fps = 0
    this.lastTime = 0
    this.frameCount = 0
    this.isRunning = false
    this.callbacks = []
    this.history = []
    this.maxHistory = 60 // 保存60秒的历史数据
  }
  
  // 开始监控
  start() {
    if (this.isRunning) return
    
    this.isRunning = true
    this.lastTime = Date.now()
    this.frameCount = 0
    
    this.tick()
  }
  
  // 停止监控
  stop() {
    this.isRunning = false
  }
  
  // 帧计算
  tick() {
    if (!this.isRunning) return
    
    this.frameCount++
    const currentTime = Date.now()
    
    // 每秒计算一次FPS
    if (currentTime - this.lastTime >= 1000) {
      this.fps = Math.round((this.frameCount * 1000) / (currentTime - this.lastTime))
      
      // 保存历史数据
      this.history.push({
        fps: this.fps,
        timestamp: currentTime
      })
      
      // 限制历史数据长度
      if (this.history.length > this.maxHistory) {
        this.history.shift()
      }
      
      // 通知回调
      this.callbacks.forEach(callback => {
        try {
          callback(this.fps)
        } catch (error) {
          console.error('FPS回调执行失败:', error)
        }
      })
      
      // 低FPS警告
      if (this.fps < 30) {
        console.warn('FPS过低:', this.fps)
      }
      
      this.frameCount = 0
      this.lastTime = currentTime
    }
    
    // 使用requestAnimationFrame或setTimeout
    if (typeof requestAnimationFrame !== 'undefined') {
      requestAnimationFrame(() => this.tick())
    } else {
      setTimeout(() => this.tick(), 16) // 约60FPS
    }
  }
  
  // 添加FPS变化回调
  onFPSChange(callback) {
    this.callbacks.push(callback)
  }
  
  // 移除FPS变化回调
  offFPSChange(callback) {
    const index = this.callbacks.indexOf(callback)
    if (index > -1) {
      this.callbacks.splice(index, 1)
    }
  }
  
  // 获取当前FPS
  getCurrentFPS() {
    return this.fps
  }
  
  // 获取平均FPS
  getAverageFPS() {
    if (this.history.length === 0) return 0
    
    const sum = this.history.reduce((total, item) => total + item.fps, 0)
    return Math.round(sum / this.history.length)
  }
  
  // 获取最低FPS
  getMinFPS() {
    if (this.history.length === 0) return 0
    
    return Math.min(...this.history.map(item => item.fps))
  }
  
  // 获取最高FPS
  getMaxFPS() {
    if (this.history.length === 0) return 0
    
    return Math.max(...this.history.map(item => item.fps))
  }
  
  // 获取FPS统计
  getStats() {
    return {
      current: this.getCurrentFPS(),
      average: this.getAverageFPS(),
      min: this.getMinFPS(),
      max: this.getMaxFPS(),
      history: this.history.slice()
    }
  }
  
  // 重置统计
  reset() {
    this.fps = 0
    this.frameCount = 0
    this.history = []
    this.lastTime = Date.now()
  }
}

// 创建FPS监控实例
const fpsMonitor = new FPSMonitor()

export default fpsMonitor

2. 代码优化

2.1 组件优化

<!-- 优化前的组件 -->
<template>
  <view class="product-list">
    <view 
      v-for="product in products" 
      :key="product.id"
      class="product-item"
      @click="onProductClick(product)"
    >
      <image :src="product.image" mode="aspectFill" />
      <view class="product-info">
        <text class="product-name">{{ product.name }}</text>
        <text class="product-price">¥{{ formatPrice(product.price) }}</text>
        <text class="product-sales">已售{{ product.sales }}件</text>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  props: {
    products: {
      type: Array,
      default: () => []
    }
  },
  
  methods: {
    // 每次渲染都会执行,性能差
    formatPrice(price) {
      return (price / 100).toFixed(2)
    },
    
    onProductClick(product) {
      uni.navigateTo({
        url: `/pages/product/detail?id=${product.id}`
      })
    }
  }
}
</script>
<!-- 优化后的组件 -->
<template>
  <view class="product-list">
    <view 
      v-for="product in optimizedProducts" 
      :key="product.id"
      class="product-item"
      @click="onProductClick(product.id)"
    >
      <image 
        :src="product.image" 
        mode="aspectFill"
        :lazy-load="true"
        @error="onImageError"
      />
      <view class="product-info">
        <text class="product-name">{{ product.name }}</text>
        <text class="product-price">¥{{ product.formattedPrice }}</text>
        <text class="product-sales">已售{{ product.sales }}件</text>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  props: {
    products: {
      type: Array,
      default: () => []
    }
  },
  
  computed: {
    // 使用计算属性预处理数据
    optimizedProducts() {
      return this.products.map(product => ({
        ...product,
        formattedPrice: this.formatPrice(product.price)
      }))
    }
  },
  
  methods: {
    formatPrice(price) {
      return (price / 100).toFixed(2)
    },
    
    // 避免传递整个对象,减少内存占用
    onProductClick(productId) {
      uni.navigateTo({
        url: `/pages/product/detail?id=${productId}`
      })
    },
    
    onImageError(e) {
      // 图片加载失败处理
      console.log('图片加载失败:', e)
    }
  }
}
</script>

2.2 列表优化

<!-- 虚拟列表组件 -->
<template>
  <scroll-view 
    class="virtual-list"
    :scroll-y="true"
    :style="{ height: containerHeight + 'px' }"
    @scroll="onScroll"
    :scroll-top="scrollTop"
  >
    <!-- 占位元素,撑开滚动高度 -->
    <view :style="{ height: totalHeight + 'px', position: 'relative' }">
      <!-- 可见区域的列表项 -->
      <view 
        v-for="item in visibleItems" 
        :key="item.id"
        class="list-item"
        :style="{
          position: 'absolute',
          top: item.top + 'px',
          left: 0,
          right: 0,
          height: itemHeight + 'px'
        }"
      >
        <slot :item="item.data" :index="item.index"></slot>
      </view>
    </view>
  </scroll-view>
</template>

<script>
export default {
  name: 'VirtualList',
  props: {
    items: {
      type: Array,
      default: () => []
    },
    itemHeight: {
      type: Number,
      default: 100
    },
    containerHeight: {
      type: Number,
      default: 600
    },
    bufferSize: {
      type: Number,
      default: 5
    }
  },
  
  data() {
    return {
      scrollTop: 0,
      startIndex: 0,
      endIndex: 0
    }
  },
  
  computed: {
    totalHeight() {
      return this.items.length * this.itemHeight
    },
    
    visibleCount() {
      return Math.ceil(this.containerHeight / this.itemHeight)
    },
    
    visibleItems() {
      const start = Math.max(0, this.startIndex - this.bufferSize)
      const end = Math.min(this.items.length, this.endIndex + this.bufferSize)
      
      const items = []
      for (let i = start; i < end; i++) {
        items.push({
          id: this.items[i].id || i,
          index: i,
          data: this.items[i],
          top: i * this.itemHeight
        })
      }
      
      return items
    }
  },
  
  watch: {
    items: {
      handler() {
        this.updateVisibleRange()
      },
      immediate: true
    }
  },
  
  methods: {
    onScroll(e) {
      this.scrollTop = e.detail.scrollTop
      this.updateVisibleRange()
    },
    
    updateVisibleRange() {
      this.startIndex = Math.floor(this.scrollTop / this.itemHeight)
      this.endIndex = this.startIndex + this.visibleCount
    },
    
    scrollToIndex(index) {
      this.scrollTop = index * this.itemHeight
    }
  }
}
</script>

<style lang="scss" scoped>
.virtual-list {
  overflow: hidden;
}

.list-item {
  box-sizing: border-box;
}
</style>

2.3 图片优化

// utils/imageOptimizer.js
class ImageOptimizer {
  constructor() {
    this.cache = new Map()
    this.loadingQueue = new Map()
    this.maxCacheSize = 50
    this.defaultPlaceholder = '/static/images/placeholder.png'
  }
  
  // 获取优化后的图片URL
  getOptimizedImageUrl(originalUrl, options = {}) {
    if (!originalUrl) return this.defaultPlaceholder
    
    const {
      width = 0,
      height = 0,
      quality = 80,
      format = 'webp',
      mode = 'aspectFill'
    } = options
    
    // 如果是本地图片,直接返回
    if (originalUrl.startsWith('/static') || originalUrl.startsWith('data:')) {
      return originalUrl
    }
    
    // 生成缓存key
    const cacheKey = `${originalUrl}_${width}_${height}_${quality}_${format}`
    
    // 检查缓存
    if (this.cache.has(cacheKey)) {
      return this.cache.get(cacheKey)
    }
    
    // 构建优化URL(根据实际图片服务调整)
    let optimizedUrl = originalUrl
    
    // 示例:阿里云OSS图片处理
    if (originalUrl.includes('aliyuncs.com')) {
      const params = []
      if (width && height) {
        params.push(`resize,m_fill,w_${width},h_${height}`)
      } else if (width) {
        params.push(`resize,w_${width}`)
      } else if (height) {
        params.push(`resize,h_${height}`)
      }
      
      if (quality < 100) {
        params.push(`quality,q_${quality}`)
      }
      
      if (format && format !== 'jpg') {
        params.push(`format,${format}`)
      }
      
      if (params.length > 0) {
        optimizedUrl = `${originalUrl}?x-oss-process=image/${params.join('/')}`
      }
    }
    
    // 示例:腾讯云COS图片处理
    else if (originalUrl.includes('myqcloud.com')) {
      const params = []
      if (width && height) {
        params.push(`thumbnail/${width}x${height}`)
      }
      
      if (quality < 100) {
        params.push(`quality/${quality}`)
      }
      
      if (format && format !== 'jpg') {
        params.push(`format/${format}`)
      }
      
      if (params.length > 0) {
        optimizedUrl = `${originalUrl}?imageMogr2/${params.join('/')}`
      }
    }
    
    // 缓存结果
    this.setCache(cacheKey, optimizedUrl)
    
    return optimizedUrl
  }
  
  // 预加载图片
  preloadImage(url, options = {}) {
    const optimizedUrl = this.getOptimizedImageUrl(url, options)
    
    return new Promise((resolve, reject) => {
      // 检查是否已在加载队列中
      if (this.loadingQueue.has(optimizedUrl)) {
        this.loadingQueue.get(optimizedUrl).then(resolve).catch(reject)
        return
      }
      
      // 创建加载Promise
      const loadPromise = new Promise((res, rej) => {
        const image = new Image()
        
        image.onload = () => {
          this.loadingQueue.delete(optimizedUrl)
          res(optimizedUrl)
        }
        
        image.onerror = () => {
          this.loadingQueue.delete(optimizedUrl)
          rej(new Error(`图片加载失败: ${optimizedUrl}`))
        }
        
        image.src = optimizedUrl
      })
      
      this.loadingQueue.set(optimizedUrl, loadPromise)
      loadPromise.then(resolve).catch(reject)
    })
  }
  
  // 批量预加载
  async preloadImages(urls, options = {}) {
    const promises = urls.map(url => this.preloadImage(url, options))
    
    try {
      const results = await Promise.allSettled(promises)
      const successful = results.filter(r => r.status === 'fulfilled').length
      const failed = results.filter(r => r.status === 'rejected').length
      
      console.log(`图片预加载完成: 成功${successful}张, 失败${failed}张`)
      return results
    } catch (error) {
      console.error('批量预加载失败:', error)
      throw error
    }
  }
  
  // 设置缓存
  setCache(key, value) {
    // 如果缓存已满,删除最旧的
    if (this.cache.size >= this.maxCacheSize) {
      const firstKey = this.cache.keys().next().value
      this.cache.delete(firstKey)
    }
    
    this.cache.set(key, value)
  }
  
  // 清理缓存
  clearCache() {
    this.cache.clear()
    this.loadingQueue.clear()
  }
  
  // 获取缓存统计
  getCacheStats() {
    return {
      cacheSize: this.cache.size,
      loadingCount: this.loadingQueue.size,
      maxCacheSize: this.maxCacheSize
    }
  }
}

// 创建图片优化器实例
const imageOptimizer = new ImageOptimizer()

export default imageOptimizer

2.4 内存优化

// utils/memoryManager.js
class MemoryManager {
  constructor() {
    this.watchers = []
    this.cleanupTasks = []
    this.memoryThreshold = 0.8 // 80%内存使用率阈值
    
    this.init()
  }
  
  // 初始化内存管理
  init() {
    this.startMemoryMonitoring()
    this.setupPageCleanup()
  }
  
  // 开始内存监控
  startMemoryMonitoring() {
    setInterval(() => {
      this.checkMemoryUsage()
    }, 10000) // 每10秒检查一次
  }
  
  // 检查内存使用情况
  checkMemoryUsage() {
    // #ifdef H5
    if (performance.memory) {
      const { usedJSHeapSize, totalJSHeapSize } = performance.memory
      const usageRate = usedJSHeapSize / totalJSHeapSize
      
      if (usageRate > this.memoryThreshold) {
        console.warn('内存使用率过高,开始清理:', usageRate)
        this.performCleanup()
      }
    }
    // #endif
  }
  
  // 执行内存清理
  performCleanup() {
    // 清理图片缓存
    this.clearImageCache()
    
    // 清理数据缓存
    this.clearDataCache()
    
    // 执行自定义清理任务
    this.runCleanupTasks()
    
    // 强制垃圾回收(如果支持)
    this.forceGarbageCollection()
  }
  
  // 清理图片缓存
  clearImageCache() {
    try {
      // 清理uni-app图片缓存
      uni.clearStorageSync()
      
      // 清理自定义图片缓存
      if (window.imageOptimizer) {
        window.imageOptimizer.clearCache()
      }
      
      console.log('图片缓存已清理')
    } catch (error) {
      console.error('清理图片缓存失败:', error)
    }
  }
  
  // 清理数据缓存
  clearDataCache() {
    try {
      // 清理过期的本地存储
      const keys = uni.getStorageInfoSync().keys
      const now = Date.now()
      
      keys.forEach(key => {
        if (key.startsWith('cache_')) {
          try {
            const data = uni.getStorageSync(key)
            if (data && data.expireTime && data.expireTime < now) {
              uni.removeStorageSync(key)
            }
          } catch (error) {
            // 忽略解析错误,直接删除
            uni.removeStorageSync(key)
          }
        }
      })
      
      console.log('数据缓存已清理')
    } catch (error) {
      console.error('清理数据缓存失败:', error)
    }
  }
  
  // 运行清理任务
  runCleanupTasks() {
    this.cleanupTasks.forEach(task => {
      try {
        task()
      } catch (error) {
        console.error('清理任务执行失败:', error)
      }
    })
  }
  
  // 强制垃圾回收
  forceGarbageCollection() {
    // #ifdef H5
    if (window.gc) {
      window.gc()
      console.log('已执行垃圾回收')
    }
    // #endif
  }
  
  // 设置页面清理
  setupPageCleanup() {
    // 监听页面隐藏事件
    uni.$on('onHide', () => {
      this.performLightCleanup()
    })
    
    // 监听页面卸载事件
    uni.$on('onUnload', () => {
      this.performPageCleanup()
    })
  }
  
  // 轻量级清理(页面隐藏时)
  performLightCleanup() {
    // 清理定时器
    this.clearTimers()
    
    // 暂停动画
    this.pauseAnimations()
  }
  
  // 页面清理(页面卸载时)
  performPageCleanup() {
    // 清理事件监听器
    this.clearEventListeners()
    
    // 清理定时器
    this.clearTimers()
    
    // 清理观察者
    this.clearObservers()
  }
  
  // 清理定时器
  clearTimers() {
    // 这里需要应用层配合,记录所有定时器ID
    const app = getApp()
    if (app && app.globalData && app.globalData.timers) {
      app.globalData.timers.forEach(timerId => {
        clearTimeout(timerId)
        clearInterval(timerId)
      })
      app.globalData.timers = []
    }
  }
  
  // 暂停动画
  pauseAnimations() {
    // 暂停CSS动画
    const animatedElements = document.querySelectorAll('.animate')
    animatedElements.forEach(el => {
      el.style.animationPlayState = 'paused'
    })
  }
  
  // 清理事件监听器
  clearEventListeners() {
    this.watchers.forEach(watcher => {
      if (typeof watcher === 'function') {
        watcher()
      }
    })
    this.watchers = []
  }
  
  // 清理观察者
  clearObservers() {
    // 清理Intersection Observer
    if (window.intersectionObservers) {
      window.intersectionObservers.forEach(observer => {
        observer.disconnect()
      })
      window.intersectionObservers = []
    }
    
    // 清理Mutation Observer
    if (window.mutationObservers) {
      window.mutationObservers.forEach(observer => {
        observer.disconnect()
      })
      window.mutationObservers = []
    }
  }
  
  // 注册清理任务
  registerCleanupTask(task) {
    if (typeof task === 'function') {
      this.cleanupTasks.push(task)
    }
  }
  
  // 注册观察者
  registerWatcher(watcher) {
    if (typeof watcher === 'function') {
      this.watchers.push(watcher)
    }
  }
  
  // 获取内存使用情况
  getMemoryUsage() {
    // #ifdef H5
    if (performance.memory) {
      return {
        used: performance.memory.usedJSHeapSize,
        total: performance.memory.totalJSHeapSize,
        limit: performance.memory.jsHeapSizeLimit,
        usageRate: performance.memory.usedJSHeapSize / performance.memory.totalJSHeapSize
      }
    }
    // #endif
    
    return null
  }
}

// 创建内存管理器实例
const memoryManager = new MemoryManager()

export default memoryManager

3. 调试技巧

3.1 调试工具

// utils/debugger.js
class Debugger {
  constructor() {
    this.isDebugMode = false
    this.logs = []
    this.maxLogs = 1000
    this.filters = {
      level: ['log', 'warn', 'error'],
      category: []
    }
    
    this.init()
  }
  
  // 初始化调试器
  init() {
    // 检查是否为调试模式
    this.isDebugMode = this.checkDebugMode()
    
    if (this.isDebugMode) {
      this.setupConsoleProxy()
      this.setupErrorHandler()
      this.setupNetworkMonitor()
    }
  }
  
  // 检查调试模式
  checkDebugMode() {
    // #ifdef H5
    return location.hostname === 'localhost' || 
           location.hostname === '127.0.0.1' ||
           location.search.includes('debug=true')
    // #endif
    
    // #ifdef APP-PLUS
    return plus.runtime.isDebugMode
    // #endif
    
    // #ifdef MP
    return wx.getAccountInfoSync().miniProgram.envVersion === 'develop'
    // #endif
    
    return false
  }
  
  // 设置控制台代理
  setupConsoleProxy() {
    const originalConsole = {
      log: console.log,
      warn: console.warn,
      error: console.error,
      info: console.info
    }
    
    Object.keys(originalConsole).forEach(level => {
      console[level] = (...args) => {
        // 记录日志
        this.addLog(level, args)
        
        // 调用原始方法
        originalConsole[level].apply(console, args)
      }
    })
  }
  
  // 设置错误处理
  setupErrorHandler() {
    // #ifdef H5
    window.addEventListener('error', (event) => {
      this.addLog('error', [{
        type: 'javascript',
        message: event.message,
        filename: event.filename,
        lineno: event.lineno,
        colno: event.colno,
        stack: event.error?.stack
      }])
    })
    
    window.addEventListener('unhandledrejection', (event) => {
      this.addLog('error', [{
        type: 'promise',
        message: event.reason?.message || event.reason,
        stack: event.reason?.stack
      }])
    })
    // #endif
  }
  
  // 设置网络监控
  setupNetworkMonitor() {
    const originalRequest = uni.request
    
    uni.request = (options) => {
      const startTime = Date.now()
      
      this.addLog('info', [{
        type: 'network',
        action: 'request',
        url: options.url,
        method: options.method || 'GET',
        data: options.data,
        timestamp: startTime
      }])
      
      const originalSuccess = options.success
      const originalFail = options.fail
      
      options.success = (res) => {
        this.addLog('info', [{
          type: 'network',
          action: 'response',
          url: options.url,
          statusCode: res.statusCode,
          data: res.data,
          duration: Date.now() - startTime,
          timestamp: Date.now()
        }])
        
        if (originalSuccess) originalSuccess(res)
      }
      
      options.fail = (err) => {
        this.addLog('error', [{
          type: 'network',
          action: 'error',
          url: options.url,
          error: err,
          duration: Date.now() - startTime,
          timestamp: Date.now()
        }])
        
        if (originalFail) originalFail(err)
      }
      
      return originalRequest(options)
    }
  }
  
  // 添加日志
  addLog(level, args) {
    const log = {
      id: Date.now() + Math.random(),
      level,
      args,
      timestamp: Date.now(),
      stack: new Error().stack
    }
    
    this.logs.push(log)
    
    // 限制日志数量
    if (this.logs.length > this.maxLogs) {
      this.logs = this.logs.slice(-this.maxLogs / 2)
    }
    
    // 发送到调试面板
    this.sendToDebugPanel(log)
  }
  
  // 发送到调试面板
  sendToDebugPanel(log) {
    uni.$emit('debugLog', log)
  }
  
  // 获取过滤后的日志
  getFilteredLogs() {
    return this.logs.filter(log => {
      // 级别过滤
      if (!this.filters.level.includes(log.level)) {
        return false
      }
      
      // 分类过滤
      if (this.filters.category.length > 0) {
        const category = log.args[0]?.type
        if (!this.filters.category.includes(category)) {
          return false
        }
      }
      
      return true
    })
  }
  
  // 设置过滤器
  setFilter(type, values) {
    if (this.filters[type]) {
      this.filters[type] = values
    }
  }
  
  // 清空日志
  clearLogs() {
    this.logs = []
  }
  
  // 导出日志
  exportLogs() {
    const data = {
      logs: this.logs,
      timestamp: Date.now(),
      userAgent: navigator.userAgent,
      deviceInfo: uni.getSystemInfoSync()
    }
    
    return JSON.stringify(data, null, 2)
  }
  
  // 性能标记
  mark(name) {
    if (this.isDebugMode) {
      console.time(name)
      this.addLog('info', [{
        type: 'performance',
        action: 'mark',
        name,
        timestamp: Date.now()
      }])
    }
  }
  
  // 性能测量
  measure(name) {
    if (this.isDebugMode) {
      console.timeEnd(name)
      this.addLog('info', [{
        type: 'performance',
        action: 'measure',
        name,
        timestamp: Date.now()
      }])
    }
  }
  
  // 断言
  assert(condition, message) {
    if (!condition) {
      const error = new Error(message || 'Assertion failed')
      this.addLog('error', [{
        type: 'assertion',
        message: error.message,
        stack: error.stack
      }])
      throw error
    }
  }
  
  // 调试信息
  debug(category, data) {
    if (this.isDebugMode) {
      this.addLog('log', [{
        type: 'debug',
        category,
        data,
        timestamp: Date.now()
      }])
    }
  }
}

// 创建调试器实例
const debugger = new Debugger()

export default debugger

3.2 调试面板组件

<!-- components/DebugPanel.vue -->
<template>
  <view v-if="visible" class="debug-panel">
    <view class="debug-header">
      <text class="debug-title">调试面板</text>
      <view class="debug-actions">
        <button @click="clearLogs" size="mini">清空</button>
        <button @click="exportLogs" size="mini">导出</button>
        <button @click="close" size="mini">关闭</button>
      </view>
    </view>
    
    <view class="debug-filters">
      <view class="filter-group">
        <text class="filter-label">级别:</text>
        <checkbox-group @change="onLevelChange">
          <label v-for="level in levels" :key="level">
            <checkbox :value="level" :checked="selectedLevels.includes(level)" />
            <text>{{ level }}</text>
          </label>
        </checkbox-group>
      </view>
    </view>
    
    <scroll-view class="debug-logs" scroll-y>
      <view 
        v-for="log in filteredLogs" 
        :key="log.id"
        class="log-item"
        :class="`log-${log.level}`"
      >
        <view class="log-header">
          <text class="log-time">{{ formatTime(log.timestamp) }}</text>
          <text class="log-level">{{ log.level.toUpperCase() }}</text>
        </view>
        <view class="log-content">
          <text>{{ formatLogContent(log.args) }}</text>
        </view>
        <view v-if="log.stack" class="log-stack">
          <text>{{ log.stack }}</text>
        </view>
      </view>
    </scroll-view>
    
    <view class="debug-stats">
      <text>总日志: {{ logs.length }}</text>
      <text>内存: {{ memoryUsage }}</text>
      <text>FPS: {{ currentFPS }}</text>
    </view>
  </view>
  
  <!-- 调试按钮 -->
  <view v-if="!visible" class="debug-trigger" @click="show">
    <text class="debug-icon">🐛</text>
  </view>
</template>

<script>
import debugger from '@/utils/debugger.js'
import fpsMonitor from '@/utils/fpsMonitor.js'
import memoryManager from '@/utils/memoryManager.js'

export default {
  name: 'DebugPanel',
  
  data() {
    return {
      visible: false,
      logs: [],
      levels: ['log', 'info', 'warn', 'error'],
      selectedLevels: ['log', 'info', 'warn', 'error'],
      currentFPS: 0,
      memoryUsage: '0MB'
    }
  },
  
  computed: {
    filteredLogs() {
      return this.logs.filter(log => 
        this.selectedLevels.includes(log.level)
      ).slice(-100) // 只显示最近100条
    }
  },
  
  mounted() {
    this.init()
  },
  
  methods: {
    init() {
      // 监听调试日志
      uni.$on('debugLog', this.onDebugLog)
      
      // 监听FPS变化
      fpsMonitor.onFPSChange(this.onFPSChange)
      fpsMonitor.start()
      
      // 定期更新内存使用情况
      setInterval(() => {
        this.updateMemoryUsage()
      }, 5000)
    },
    
    show() {
      this.visible = true
      this.logs = debugger.getFilteredLogs()
    },
    
    close() {
      this.visible = false
    },
    
    onDebugLog(log) {
      this.logs.push(log)
      
      // 限制日志数量
      if (this.logs.length > 1000) {
        this.logs = this.logs.slice(-500)
      }
    },
    
    onFPSChange(fps) {
      this.currentFPS = fps
    },
    
    updateMemoryUsage() {
      const usage = memoryManager.getMemoryUsage()
      if (usage) {
        this.memoryUsage = `${Math.round(usage.used / 1024 / 1024)}MB`
      }
    },
    
    onLevelChange(e) {
      this.selectedLevels = e.detail.value
    },
    
    clearLogs() {
      this.logs = []
      debugger.clearLogs()
    },
    
    exportLogs() {
      const data = debugger.exportLogs()
      
      // #ifdef H5
      const blob = new Blob([data], { type: 'application/json' })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = `debug-logs-${Date.now()}.json`
      a.click()
      URL.revokeObjectURL(url)
      // #endif
      
      // #ifdef APP-PLUS
      uni.showModal({
        title: '导出日志',
        content: '日志已复制到剪贴板',
        showCancel: false
      })
      uni.setClipboardData({
        data
      })
      // #endif
    },
    
    formatTime(timestamp) {
      const date = new Date(timestamp)
      return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}`
    },
    
    formatLogContent(args) {
      return args.map(arg => {
        if (typeof arg === 'object') {
          return JSON.stringify(arg, null, 2)
        }
        return String(arg)
      }).join(' ')
    }
  },
  
  beforeDestroy() {
    uni.$off('debugLog', this.onDebugLog)
    fpsMonitor.offFPSChange(this.onFPSChange)
    fpsMonitor.stop()
  }
}
</script>

<style lang="scss" scoped>
.debug-panel {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.9);
  color: #fff;
  z-index: 9999;
  display: flex;
  flex-direction: column;
}

.debug-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20rpx;
  border-bottom: 1rpx solid #333;
}

.debug-title {
  font-size: 32rpx;
  font-weight: bold;
}

.debug-actions {
  display: flex;
  gap: 10rpx;
}

.debug-filters {
  padding: 20rpx;
  border-bottom: 1rpx solid #333;
}

.filter-group {
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.filter-label {
  font-size: 28rpx;
}

.debug-logs {
  flex: 1;
  padding: 20rpx;
}

.log-item {
  margin-bottom: 20rpx;
  padding: 15rpx;
  border-radius: 8rpx;
  background-color: rgba(255, 255, 255, 0.1);
  
  &.log-error {
    background-color: rgba(255, 0, 0, 0.2);
  }
  
  &.log-warn {
    background-color: rgba(255, 165, 0, 0.2);
  }
  
  &.log-info {
    background-color: rgba(0, 123, 255, 0.2);
  }
}

.log-header {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10rpx;
}

.log-time {
  font-size: 24rpx;
  color: #ccc;
}

.log-level {
  font-size: 24rpx;
  font-weight: bold;
}

.log-content {
  font-size: 26rpx;
  word-break: break-all;
}

.log-stack {
  margin-top: 10rpx;
  font-size: 22rpx;
  color: #999;
  white-space: pre-wrap;
}

.debug-stats {
  display: flex;
  justify-content: space-around;
  padding: 20rpx;
  border-top: 1rpx solid #333;
  font-size: 24rpx;
}

.debug-trigger {
  position: fixed;
  top: 100rpx;
  right: 20rpx;
  width: 80rpx;
  height: 80rpx;
  background-color: rgba(0, 0, 0, 0.7);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9998;
}

.debug-icon {
  font-size: 40rpx;
}
</style>

4. 总结

性能优化与调试是UniApp开发的重要环节:

  1. 性能监控:实时监控应用性能指标,及时发现问题
  2. 代码优化:通过组件优化、列表虚拟化、图片优化等提升性能
  3. 内存管理:合理管理内存使用,避免内存泄漏
  4. 调试工具:使用专业的调试工具快速定位问题
  5. 性能测试:定期进行性能测试,确保应用质量
  6. 最佳实践:遵循性能优化的最佳实践
  7. 持续优化:建立性能优化的持续改进机制