🚀 应用出了问题你都不知道,别着急我来帮你

🎯 学习目标:掌握前端监控体系的核心指标和搭建方法,让线上问题无处遁形

📊 难度等级 :中级-高级

🏷️ 技术标签#前端监控 #性能指标 #用户体验 #错误监控

⏱️ 阅读时间:约8分钟


🌟 引言

在日常的前端开发中,你是否遇到过这样的困扰:

  • 线上问题难发现:用户反馈问题时,开发者才知道出了bug
  • 性能问题无法量化:不知道页面加载到底有多慢,用户体验如何
  • 错误排查困难:线上报错信息不完整,无法快速定位问题
  • 用户行为不透明:不了解用户真实的使用情况和痛点

今天分享5个前端监控体系的关键指标和搭建方法,让你的应用问题无处遁形,用户体验持续优化!


💡 核心技巧详解

1. Core Web Vitals监控:用户体验的量化标准

🔍 应用场景

谷歌推出的Core Web Vitals是衡量用户体验的核心指标,包括LCP、FID、CLS三个关键指标。

❌ 常见问题

很多开发者只关注功能实现,忽略了用户体验的量化监控。

javascript 复制代码
// ❌ 传统做法:没有性能监控
window.onload = () => {
  console.log('页面加载完成');
};

✅ 推荐方案

使用Web Vitals库监控核心性能指标。

javascript 复制代码
/**
 * Core Web Vitals监控实现
 * @description 监控LCP、FID、CLS三个核心指标
 * @param {Function} onPerfEntry - 性能数据回调函数
 */
const monitorWebVitals = (onPerfEntry) => {
  // 动态导入web-vitals库
  import('web-vitals').then(({ getCLS, getINP, getLCP }) => {
    // 监控Cumulative Layout Shift (布局偏移)
    getCLS(onPerfEntry);
    // 监控Interaction to Next Paint (交互到下次绘制)
    getINP(onPerfEntry);
    // 监控Largest Contentful Paint (最大内容绘制)
    getLCP(onPerfEntry);
  });
};

/**
 * 性能数据处理函数
 * @description 处理并上报性能指标数据
 * @param {Object} metric - 性能指标对象
 */
const handlePerfEntry = (metric) => {
  const { name, value, id } = metric;
  
  // 发送性能数据到监控平台
  sendToAnalytics({
    metric_name: name,
    metric_value: value,
    metric_id: id,
    timestamp: Date.now(),
    page_url: window.location.href
  });
};

// 启动监控
monitorWebVitals(handlePerfEntry);

💡 核心要点

  • LCP < 2.5s:最大内容绘制时间,衡量加载性能
  • INP < 200ms:交互到下次绘制,衡量交互性能(2024年3月已替代FID)
  • CLS < 0.1:累积布局偏移,衡量视觉稳定性

🎯 实际应用

在Vue3项目中集成性能监控:

javascript 复制代码
// 在main.js中集成
import { createApp } from 'vue';
import App from './App.vue';

const app = createApp(App);

// 应用挂载后启动监控
app.mount('#app');
monitorWebVitals(handlePerfEntry);

2. JavaScript错误监控:异常捕获与上报系统

🔍 应用场景

捕获并上报JavaScript运行时错误、Promise异常、资源加载失败等问题。

❌ 常见问题

只在开发环境处理错误,线上错误无法及时发现和处理。

javascript 复制代码
// ❌ 传统做法:只有console.error
try {
  // 业务代码
} catch (error) {
  console.error('出错了:', error);
}

✅ 推荐方案

建立完整的错误监控体系。

javascript 复制代码
/**
 * 全局错误监控系统
 * @description 捕获并上报各种类型的JavaScript错误
 */
class ErrorMonitor {
  constructor() {
    this.init();
  }

  /**
   * 初始化错误监控
   * @description 设置全局错误监听器
   */
  init = () => {
    // 监听JavaScript运行时错误
    window.addEventListener('error', this.handleError);
    
    // 监听Promise未捕获的异常
    window.addEventListener('unhandledrejection', this.handlePromiseError);
    
    // 监听资源加载错误
    window.addEventListener('error', this.handleResourceError, true);
  };

  /**
   * 处理JavaScript错误
   * @description 处理运行时错误并上报
   * @param {ErrorEvent} event - 错误事件对象
   */
  handleError = (event) => {
    const errorInfo = {
      type: 'javascript_error',
      message: event.message,
      filename: event.filename,
      lineno: event.lineno,
      colno: event.colno,
      stack: event.error?.stack,
      timestamp: Date.now(),
      user_agent: navigator.userAgent,
      page_url: window.location.href
    };
    
    this.reportError(errorInfo);
  };

  /**
   * 处理Promise异常
   * @description 处理未捕获的Promise异常
   * @param {PromiseRejectionEvent} event - Promise异常事件
   */
  handlePromiseError = (event) => {
    const errorInfo = {
      type: 'promise_error',
      message: event.reason?.message || event.reason,
      stack: event.reason?.stack,
      timestamp: Date.now(),
      page_url: window.location.href
    };
    
    this.reportError(errorInfo);
  };

  /**
   * 上报错误信息
   * @description 将错误信息发送到监控平台
   * @param {Object} errorInfo - 错误信息对象
   */
  reportError = (errorInfo) => {
    // 使用beacon API确保数据发送
    if (navigator.sendBeacon) {
      navigator.sendBeacon('/api/error-report', JSON.stringify(errorInfo));
    } else {
      fetch('/api/error-report', {
        method: 'POST',
        body: JSON.stringify(errorInfo),
        headers: { 'Content-Type': 'application/json' }
      }).catch(() => {});
    }
  };
}

// 启动错误监控
const errorMonitor = new ErrorMonitor();

💡 核心要点

  • 全局捕获:监听window的error和unhandledrejection事件
  • 详细信息:收集错误堆栈、文件位置、用户环境等信息
  • 可靠上报:使用sendBeacon API确保数据发送成功

🎯 实际应用

Vue3项目中的错误边界处理:

javascript 复制代码
// Vue3全局错误处理
app.config.errorHandler = (err, vm, info) => {
  const errorInfo = {
    type: 'vue_error',
    message: err.message,
    stack: err.stack,
    component_info: info,
    timestamp: Date.now()
  };
  
  errorMonitor.reportError(errorInfo);
};

3. 用户行为分析:页面访问与操作轨迹追踪

🔍 应用场景

追踪用户的页面访问路径、点击行为、停留时间等,分析用户使用习惯。

❌ 常见问题

缺乏用户行为数据,无法了解用户真实的使用情况和痛点。

javascript 复制代码
// ❌ 传统做法:没有用户行为追踪
button.addEventListener('click', () => {
  // 只处理业务逻辑
  handleButtonClick();
});

✅ 推荐方案

建立用户行为追踪系统。

javascript 复制代码
/**
 * 用户行为追踪系统
 * @description 追踪用户的各种操作行为
 */
class UserBehaviorTracker {
  constructor() {
    this.sessionId = this.generateSessionId();
    this.init();
  }

  /**
   * 生成会话ID
   * @description 为每个用户会话生成唯一标识
   * @returns {string} 会话ID
   */
  generateSessionId = () => {
    return Date.now().toString(36) + Math.random().toString(36).substr(2);
  };

  /**
   * 初始化行为追踪
   * @description 设置各种行为监听器
   */
  init = () => {
    // 页面访问追踪
    this.trackPageView();
    
    // 点击行为追踪
    this.trackClicks();
    
    // 页面停留时间追踪
    this.trackPageDuration();
    
    // 滚动行为追踪
    this.trackScrollBehavior();
  };

  /**
   * 追踪页面访问
   * @description 记录用户访问的页面信息
   */
  trackPageView = () => {
    const pageInfo = {
      type: 'page_view',
      session_id: this.sessionId,
      page_url: window.location.href,
      page_title: document.title,
      referrer: document.referrer,
      timestamp: Date.now(),
      screen_resolution: `${screen.width}x${screen.height}`,
      viewport_size: `${window.innerWidth}x${window.innerHeight}`
    };
    
    this.sendTrackingData(pageInfo);
  };

  /**
   * 追踪点击行为
   * @description 监听并记录用户的点击操作
   */
  trackClicks = () => {
    document.addEventListener('click', (event) => {
      const target = event.target;
      const clickInfo = {
        type: 'click',
        session_id: this.sessionId,
        element_tag: target.tagName.toLowerCase(),
        element_id: target.id,
        element_class: target.className,
        element_text: target.textContent?.slice(0, 100),
        page_url: window.location.href,
        timestamp: Date.now(),
        coordinates: { x: event.clientX, y: event.clientY }
      };
      
      this.sendTrackingData(clickInfo);
    });
  };

  /**
   * 追踪页面停留时间
   * @description 计算用户在页面的停留时间
   */
  trackPageDuration = () => {
    const startTime = Date.now();
    
    // 页面卸载时发送停留时间
    window.addEventListener('beforeunload', () => {
      const duration = Date.now() - startTime;
      const durationInfo = {
        type: 'page_duration',
        session_id: this.sessionId,
        page_url: window.location.href,
        duration: duration,
        timestamp: Date.now()
      };
      
      // 使用sendBeacon确保数据发送
      navigator.sendBeacon('/api/behavior-track', JSON.stringify(durationInfo));
    });
  };

  /**
   * 发送追踪数据
   * @description 将行为数据发送到分析平台
   * @param {Object} data - 追踪数据对象
   */
  sendTrackingData = (data) => {
    fetch('/api/behavior-track', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: { 'Content-Type': 'application/json' }
    }).catch(() => {});
  };
}

// 启动用户行为追踪
const behaviorTracker = new UserBehaviorTracker();

💡 核心要点

  • 会话管理:为每个用户会话生成唯一标识
  • 多维度追踪:页面访问、点击、停留时间、滚动等
  • 隐私保护:只收集必要的行为数据,保护用户隐私

🎯 实际应用

在Vue3路由中集成行为追踪:

javascript 复制代码
// router/index.js
import { createRouter, createWebHistory } from 'vue-router';

const router = createRouter({
  history: createWebHistory(),
  routes: [...]
});

// 路由变化时追踪页面访问
router.afterEach((to, from) => {
  behaviorTracker.trackPageView();
});

4. 性能监控:资源加载与接口响应时间分析

🔍 应用场景

监控页面资源加载时间、API接口响应时间、网络状况等性能指标。

❌ 常见问题

缺乏性能数据支撑,无法识别性能瓶颈和优化方向。

javascript 复制代码
// ❌ 传统做法:没有性能监控
fetch('/api/data')
  .then(response => response.json())
  .then(data => {
    // 处理数据
  });

✅ 推荐方案

建立全面的性能监控体系。

javascript 复制代码
/**
 * 性能监控系统
 * @description 监控资源加载和接口性能
 */
class PerformanceMonitor {
  constructor() {
    this.init();
  }

  /**
   * 初始化性能监控
   * @description 设置各种性能监听器
   */
  init = () => {
    // 监控资源加载性能
    this.monitorResourceLoading();
    
    // 监控导航性能
    this.monitorNavigationTiming();
    
    // 拦截fetch请求监控API性能
    this.interceptFetch();
  };

  /**
   * 监控资源加载性能
   * @description 监控CSS、JS、图片等资源的加载时间
   */
  monitorResourceLoading = () => {
    // 使用PerformanceObserver监控资源
    const observer = new PerformanceObserver((list) => {
      list.getEntries().forEach((entry) => {
        if (entry.entryType === 'resource') {
          const resourceInfo = {
            type: 'resource_timing',
            name: entry.name,
            duration: entry.duration,
            size: entry.transferSize,
            start_time: entry.startTime,
            response_end: entry.responseEnd,
            timestamp: Date.now()
          };
          
          this.sendPerformanceData(resourceInfo);
        }
      });
    });
    
    observer.observe({ entryTypes: ['resource'] });
  };

  /**
   * 监控导航性能
   * @description 监控页面导航的各个阶段耗时
   */
  monitorNavigationTiming = () => {
    window.addEventListener('load', () => {
      setTimeout(() => {
        const navigation = performance.getEntriesByType('navigation')[0];
        
        const timingInfo = {
          type: 'navigation_timing',
          dns_lookup: navigation.domainLookupEnd - navigation.domainLookupStart,
          tcp_connect: navigation.connectEnd - navigation.connectStart,
          request_response: navigation.responseEnd - navigation.requestStart,
          dom_parse: navigation.domContentLoadedEventEnd - navigation.responseEnd,
          resource_load: navigation.loadEventEnd - navigation.domContentLoadedEventEnd,
          total_time: navigation.loadEventEnd - navigation.navigationStart,
          timestamp: Date.now()
        };
        
        this.sendPerformanceData(timingInfo);
      }, 0);
    });
  };

  /**
   * 拦截fetch请求监控API性能
   * @description 监控API接口的响应时间和状态
   */
  interceptFetch = () => {
    const originalFetch = window.fetch;
    
    window.fetch = async (...args) => {
      const startTime = performance.now();
      const url = args[0];
      
      try {
        const response = await originalFetch(...args);
        const endTime = performance.now();
        
        // 记录API性能数据
        const apiInfo = {
          type: 'api_timing',
          url: url,
          method: args[1]?.method || 'GET',
          status: response.status,
          duration: endTime - startTime,
          success: response.ok,
          timestamp: Date.now()
        };
        
        this.sendPerformanceData(apiInfo);
        return response;
      } catch (error) {
        const endTime = performance.now();
        
        // 记录API错误
        const errorInfo = {
          type: 'api_error',
          url: url,
          method: args[1]?.method || 'GET',
          duration: endTime - startTime,
          error: error.message,
          timestamp: Date.now()
        };
        
        this.sendPerformanceData(errorInfo);
        throw error;
      }
    };
  };

  /**
   * 发送性能数据
   * @description 将性能数据发送到监控平台
   * @param {Object} data - 性能数据对象
   */
  sendPerformanceData = (data) => {
    fetch('/api/performance-monitor', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: { 'Content-Type': 'application/json' }
    }).catch(() => {});
  };
}

// 启动性能监控
const performanceMonitor = new PerformanceMonitor();

💡 核心要点

  • PerformanceObserver:使用现代API监控性能指标
  • Navigation Timing:分析页面加载各阶段的耗时
  • Resource Timing:监控资源加载性能
  • API拦截:监控接口响应时间和成功率

🎯 实际应用

在Vue3项目中集成性能监控:

javascript 复制代码
// 在axios拦截器中集成API监控
import axios from 'axios';

axios.interceptors.request.use((config) => {
  config.startTime = performance.now();
  return config;
});

axios.interceptors.response.use(
  (response) => {
    const duration = performance.now() - response.config.startTime;
    // 发送性能数据
    performanceMonitor.sendPerformanceData({
      type: 'axios_timing',
      url: response.config.url,
      duration: duration,
      status: response.status
    });
    return response;
  },
  (error) => {
    // 处理错误情况
    return Promise.reject(error);
  }
);

5. 监控平台搭建:从数据收集到可视化展示

🔍 应用场景

搭建完整的监控平台,实现数据收集、存储、分析和可视化展示。

❌ 常见问题

数据收集了但没有有效的分析和展示,无法发挥监控数据的价值。

javascript 复制代码
// ❌ 传统做法:数据只是简单存储
app.post('/api/monitor', (req, res) => {
  console.log(req.body); // 只是打印日志
  res.json({ success: true });
});

✅ 推荐方案

建立完整的监控数据处理流程。

javascript 复制代码
/**
 * 监控数据处理中心
 * @description 处理、分析和存储监控数据
 */
class MonitoringDataProcessor {
  constructor() {
    this.alertRules = new Map();
    this.init();
  }

  /**
   * 初始化监控数据处理
   * @description 设置告警规则和数据处理流程
   */
  init = () => {
    // 设置告警规则
    this.setupAlertRules();
  };

  /**
   * 设置告警规则
   * @description 定义各种监控指标的告警阈值
   */
  setupAlertRules = () => {
    // 性能告警规则
    this.alertRules.set('lcp_threshold', { value: 2500, type: 'performance' });
    this.alertRules.set('inp_threshold', { value: 200, type: 'performance' });
    this.alertRules.set('cls_threshold', { value: 0.1, type: 'performance' });
    
    // 错误率告警规则
    this.alertRules.set('error_rate', { value: 0.05, type: 'error' });
    
    // API响应时间告警
    this.alertRules.set('api_response_time', { value: 3000, type: 'api' });
  };

  /**
   * 处理监控数据
   * @description 分析监控数据并触发相应的处理逻辑
   * @param {Object} data - 监控数据对象
   */
  processMonitoringData = (data) => {
    try {
      // 数据验证和清洗
      const cleanedData = this.cleanData(data);
      
      // 存储数据
      this.storeData(cleanedData);
      
      // 实时分析
      this.analyzeData(cleanedData);
      
      // 检查告警条件
      this.checkAlerts(cleanedData);
      
    } catch (error) {
      console.error('监控数据处理失败:', error);
    }
  };

  /**
   * 数据清洗
   * @description 验证和清洗监控数据
   * @param {Object} data - 原始监控数据
   * @returns {Object} 清洗后的数据
   */
  cleanData = (data) => {
    return {
      ...data,
      timestamp: data.timestamp || Date.now(),
      session_id: data.session_id || 'unknown',
      user_agent: data.user_agent || 'unknown',
      page_url: this.sanitizeUrl(data.page_url)
    };
  };

  /**
   * 存储监控数据
   * @description 将数据存储到数据库
   * @param {Object} data - 清洗后的监控数据
   */
  storeData = async (data) => {
    // 根据数据类型存储到不同的表
    const tableName = this.getTableName(data.type);
    
    // 这里可以使用数据库ORM或直接SQL
    await this.database.insert(tableName, data);
  };

  /**
   * 实时数据分析
   * @description 对监控数据进行实时分析
   * @param {Object} data - 监控数据
   */
  analyzeData = (data) => {
    switch (data.type) {
      case 'performance':
        this.analyzePerformance(data);
        break;
      case 'error':
        this.analyzeError(data);
        break;
      case 'user_behavior':
        this.analyzeUserBehavior(data);
        break;
    }
  };

  /**
   * 检查告警条件
   * @description 根据告警规则检查是否需要发送告警
   * @param {Object} data - 监控数据
   */
  checkAlerts = (data) => {
    // 检查性能指标告警
    if (data.type === 'performance') {
      if (data.metric_name === 'LCP' && data.metric_value > 2500) {
        this.sendAlert({
          type: 'performance_alert',
          message: `LCP指标异常: ${data.metric_value}ms`,
          severity: 'warning',
          data: data
        });
      }
    }
    
    // 检查错误率告警
    if (data.type === 'error') {
      this.checkErrorRate(data);
    }
  };

  /**
   * 发送告警
   * @description 发送告警通知
   * @param {Object} alert - 告警信息
   */
  sendAlert = (alert) => {
    // 发送到钉钉、企业微信等
    this.sendToWebhook(alert);
    
    // 发送邮件通知
    this.sendEmailAlert(alert);
    
    // 记录告警日志
    console.log('告警触发:', alert);
  };

  /**
   * 获取监控仪表板数据
   * @description 为前端仪表板提供数据
   * @param {Object} params - 查询参数
   * @returns {Object} 仪表板数据
   */
  getDashboardData = async (params) => {
    const { timeRange, metrics } = params;
    
    // 查询性能指标
    const performanceData = await this.getPerformanceMetrics(timeRange);
    
    // 查询错误统计
    const errorData = await this.getErrorStatistics(timeRange);
    
    // 查询用户行为数据
    const behaviorData = await this.getUserBehaviorData(timeRange);
    
    return {
      performance: performanceData,
      errors: errorData,
      behavior: behaviorData,
      timestamp: Date.now()
    };
  };
}

// 创建监控数据处理实例
const dataProcessor = new MonitoringDataProcessor();

// Express路由处理
app.post('/api/monitor', (req, res) => {
  dataProcessor.processMonitoringData(req.body);
  res.json({ success: true });
});

// 仪表板数据接口
app.get('/api/dashboard', async (req, res) => {
  const data = await dataProcessor.getDashboardData(req.query);
  res.json(data);
});

💡 核心要点

  • 数据处理流程:收集→清洗→存储→分析→告警
  • 告警机制:设置合理的阈值和告警规则
  • 可视化展示:提供直观的监控仪表板
  • 实时性:支持实时数据分析和告警

🎯 实际应用

Vue3监控仪表板组件:

vue 复制代码
<template>
  <div class="monitoring-dashboard">
    <div class="metrics-grid">
      <MetricCard 
        title="Core Web Vitals"
        :data="performanceMetrics"
      />
      <MetricCard 
        title="错误统计"
        :data="errorMetrics"
      />
      <MetricCard 
        title="用户行为"
        :data="behaviorMetrics"
      />
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { fetchDashboardData } from '@/api/monitoring';

const performanceMetrics = ref({});
const errorMetrics = ref({});
const behaviorMetrics = ref({});

/**
 * 加载仪表板数据
 * @description 从API获取监控数据并更新界面
 */
const loadDashboardData = async () => {
  try {
    const data = await fetchDashboardData({
      timeRange: '24h',
      metrics: ['performance', 'errors', 'behavior']
    });
    
    performanceMetrics.value = data.performance;
    errorMetrics.value = data.errors;
    behaviorMetrics.value = data.behavior;
  } catch (error) {
    console.error('加载监控数据失败:', error);
  }
};

onMounted(() => {
  loadDashboardData();
  
  // 定时刷新数据
  setInterval(loadDashboardData, 30000);
});
</script>

📊 技巧对比总结

监控类型 使用场景 优势 注意事项
Core Web Vitals 用户体验量化 标准化指标,直观反映体验 需要持续优化,关注阈值变化
错误监控 异常问题发现 快速定位问题,减少故障时间 避免过度上报,注意隐私保护
行为分析 用户体验优化 了解真实使用情况 数据量大,需要合理采样
性能监控 应用性能优化 精确定位性能瓶颈 监控开销要控制在合理范围
监控平台 数据分析展示 统一管理,可视化展示 系统复杂度高,需要专业运维

🎯 实战应用建议

最佳实践

  1. 渐进式部署:从核心指标开始,逐步完善监控体系
  2. 合理采样:避免100%采集,根据业务重要性设置采样率
  3. 告警优化:设置合理的告警阈值,避免告警疲劳
  4. 数据隐私:遵循数据保护法规,只收集必要的信息
  5. 性能影响:监控代码本身要轻量,避免影响应用性能

性能考虑

  • 异步上报:使用requestIdleCallback或Web Worker进行数据上报
  • 批量发送:合并多个监控数据一次性发送,减少网络请求
  • 本地缓存:网络异常时将数据缓存到localStorage
  • 采样策略:对于高频事件使用采样,避免数据量过大

安全性注意事项

  • 数据脱敏:敏感信息要进行脱敏处理
  • 传输加密:使用HTTPS传输监控数据
  • 访问控制:监控后台要有严格的权限控制
  • 数据保留:设置合理的数据保留期限

💡 总结

这5个前端监控体系的关键指标在实际应用中能够全面保障应用质量,掌握它们能让你的应用问题无处遁形:

  1. Core Web Vitals监控:量化用户体验,提供优化方向
  2. JavaScript错误监控:快速发现和定位线上问题
  3. 用户行为分析:深入了解用户使用习惯和痛点
  4. 性能监控:精确定位性能瓶颈,指导优化工作
  5. 监控平台搭建:统一数据管理,实现可视化分析

希望这些监控技巧能帮助你在前端开发中建立完善的质量保障体系,让线上问题早发现、早解决!


🔗 相关资源


💡 今日收获:掌握了5个前端监控体系的关键指标,这些技术在保障应用质量方面非常重要。

如果这篇文章对你有帮助,欢迎点赞、收藏和分享!有任何问题也欢迎在评论区讨论。 🚀

相关推荐
mldong5 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排6 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60616 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角7 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!7 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰8 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi9 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen10 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马11 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒11 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端