IDE调试开发文档
1. 概述
梵医云前端项目基于VS Code开发环境,提供完整的调试支持,包括断点调试、控制台输出、性能分析等功能。
1.1 调试特点
- VS Code集成:使用VS Code作为主要开发IDE
- 断点调试:支持TypeScript和Vue文件的断点调试
- Source Map:完整的Source Map支持,方便调试编译后的代码
- Logger工具:内置Logger工具类,提供彩色控制台输出
- TypeScript支持:完整的TypeScript类型检查和智能提示
1.2 推荐IDE
| IDE | 支持程度 | 说明 |
|---|---|---|
| VS Code | 完全支持 | 推荐使用,项目提供完整配置 |
| WebStorm | 完全支持 | JetBrains系列IDE,功能强大 |
| Vim/Neovim | 部分支持 | 需要额外配置 |
2. VS Code配置
2.1 工作区设置
配置文件:[.vscode/settings.json](file:///e:/git.fanyicloud.com.cn/fanyi-cloud-ui/.vscode/settings.json)
{
"typescript.tsdk": "node_modules/typescript/lib",
"npm.packageManager": "pnpm",
"editor.tabSize": 2,
"prettier.printWidth": 100,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.eol": "\n",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"[vue]": {
"editor.defaultFormatter": "Vue.volar"
},
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"i18n-ally.localesPaths": ["src/locales"],
"i18n-ally.keystyle": "nested",
"i18n-ally.sortKeys": true,
"i18n-ally.namespace": false,
"i18n-ally.enabledParsers": ["ts"],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-CN"
}2.2 调试配置
配置文件:[.vscode/launch.json](file:///e:/git.fanyicloud.com.cn/fanyi-cloud-ui/.vscode/launch.json)
{
"version": "0.2.0",
"configurations": [
{
"type": "msedge",
"request": "launch",
"name": "Launch Edge against localhost",
"url": "http://localhost",
"webRoot": "${workspaceFolder}/src",
"sourceMaps": true
}
]
}2.3 推荐插件
配置文件:[.vscode/extensions.json](file:///e:/git.fanyicloud.com.cn/fanyi-cloud-ui/.vscode/extensions.json)
{
"recommendations": [
"christian-kohler.path-intellisense", // 路径智能提示
"vscode-icons-team.vscode-icons", // 文件图标
"davidanson.vscode-markdownlint", // Markdown检查
"dbaeumer.vscode-eslint", // ESLint
"esbenp.prettier-vscode", // Prettier
"mrmlnc.vscode-less", // Less支持
"lokalise.i18n-ally", // 国际化支持
"redhat.vscode-yaml", // YAML支持
"csstools.postcss", // PostCSS支持
"mikestead.dotenv", // 环境变量支持
"eamodio.gitlens", // Git增强
"antfu.iconify", // Iconify支持
"antfu.unocss", // UnoCSS支持
"Vue.volar", // Vue 3支持
"daviddai.deepseek-code-generator" // 代码生成
]
}2.4 安装推荐插件
在VS Code中按 Ctrl+Shift+X 打开扩展面板,搜索并安装推荐插件:
# 也可以通过命令行安装
code --install-extension christian-kohler.path-intellisense
code --install-extension vscode-icons-team.vscode-icons
code --install-extension dbaeumer.vscode-eslint
code --install-extension esbenp.prettier-vscode
code --install-extension Vue.volar3. 调试配置
3.1 配置Chrome调试
修改 [.vscode/launch.json](file:///e:/git.fanyicloud.com.cn/fanyi-cloud-ui/.vscode/launch.json) 添加Chrome调试配置:
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}/src",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///*": "${webRoot}/*"
}
}
]
}3.2 配置Vite开发服务器
确保 [vite.config.ts](file:///e:/git.fanyicloud.com.cn/fanyi-cloud-ui/vite.config.ts) 中启用了Source Map:
export default ({ command, mode }: ConfigEnv): UserConfig => {
return {
build: {
sourcemap: env.VITE_SOURCEMAP === 'true' ? 'inline' : false,
// ...
}
}
}在环境变量中启用Source Map:
# .env.local
VITE_SOURCEMAP=true3.3 TypeScript Source Map配置
确保 [tsconfig.json](file:///e:/git.fanyicloud.com.cn/fanyi-cloud-ui/tsconfig.json) 中启用了Source Map:
{
"compilerOptions": {
"sourceMap": true,
// ...
}
}4. 断点调试
4.1 设置断点
在VS Code中设置断点:
- 打开需要调试的文件
- 在代码行号左侧点击,设置断点(红色圆点)
- 或者使用快捷键
F9在当前行设置/取消断点
// 示例:在函数中设置断点
const fetchData = async () => {
console.log('开始获取数据') // 在这里设置断点
const res = await api.getData()
console.log('数据获取成功', res) // 在这里设置断点
return res
}4.2 启动调试
- 按
F5或点击左侧调试图标的绿色播放按钮 - 选择调试配置(如 "Launch Chrome against localhost")
- VS Code会自动打开浏览器并加载应用
- 当代码执行到断点时会自动暂停
4.3 调试控制
调试时可以使用以下控制:
| 操作 | 快捷键 | 说明 |
|---|---|---|
| 继续 | F5 | 继续执行到下一个断点 |
| 单步跳过 | F10 | 跳过当前行,不进入函数 |
| 单步进入 | F11 | 进入当前行调用的函数 |
| 单步跳出 | Shift+F11 | 跳出当前函数 |
| 重新启动 | Ctrl+Shift+F5 | 重新启动调试 |
| 停止调试 | Shift+F5 | 停止调试 |
4.4 查看变量
在调试过程中,可以查看和修改变量:
- 变量面板:左侧显示当前作用域的所有变量
- 监视面板:添加表达式监视,实时查看值的变化
- 悬停查看:鼠标悬停在变量上查看当前值
- 调试控制台:在调试控制台中执行表达式
// 在调试控制台中可以执行
console.log(variable)
variable = newValue4.5 条件断点
设置条件断点,只在满足条件时暂停:
- 右键点击断点,选择 "Edit Breakpoint"
- 输入条件表达式
// 示例:只在id为1时暂停
const handleDelete = (id: number) => {
console.log('删除', id) // 设置条件断点:id === 1
// ...
}4.6 日志点
设置日志点,不暂停程序,只输出日志:
- 右键点击断点,选择 "Add Logpoint"
- 输入要输出的表达式
// 示例:输出变量值而不暂停
const processData = (data: any) => {
// 设置日志点:{data}
return data
}5. Logger工具
5.1 Logger工具类
工具文件:[src/utils/Logger.ts](file:///e:/git.fanyicloud.com.cn/fanyi-cloud-ui/src/utils/Logger.ts)
Logger工具提供彩色控制台输出功能:
import Logger from '@/utils/Logger'
// 基础打印
Logger.print('primary', '这是一条主要信息')
Logger.print('success', '操作成功')
Logger.print('warn', '警告信息')
Logger.print('error', '错误信息')
Logger.print('info', '普通信息')
// 带背景打印
Logger.printBack('primary', '带背景的主要信息')
// 美化打印
Logger.pretty('primary', '标题', '内容')
Logger.prettySuccess('成功', '操作成功完成')
Logger.prettyWarn('警告', '请注意')
Logger.prettyError('错误', '发生错误')
Logger.prettyInfo('信息', '普通信息')
// 批量打印
Logger.prettyPrimary('标题', '内容1', '内容2', '内容3')5.2 Logger类型
| 类型 | 颜色 | 说明 |
|---|---|---|
| primary | #2d8cf0 | 主要信息 |
| success | #19be6b | 成功信息 |
| info | #909399 | 普通信息 |
| warn | #ff9900 | 警告信息 |
| error | #f03f14 | 错误信息 |
5.3 Logger使用示例
import Logger from '@/utils/Logger'
// 在组件中使用
export default defineComponent({
setup() {
const fetchData = async () => {
Logger.prettyPrimary('数据获取', '开始获取数据')
try {
const res = await api.getData()
Logger.prettySuccess('数据获取', '获取成功')
Logger.print('success', res)
return res
} catch (error) {
Logger.prettyError('数据获取', '获取失败')
Logger.print('error', error)
throw error
}
}
return { fetchData }
}
})5.4 Logger打印对象
import Logger from '@/utils/Logger'
// 打印数组
const data = [1, 2, 3, 4, 5]
Logger.print('info', data) // 使用表格形式打印
// 打印对象
const user = { name: '张三', age: 25 }
Logger.print('info', user) // 使用dir形式打印
// 打印嵌套对象
const complexData = {
users: [
{ name: '张三', age: 25 },
{ name: '李四', age: 30 }
]
}
Logger.pretty('info', '复杂数据', complexData)6. 控制台调试
6.1 浏览器控制台
在浏览器开发者工具中调试:
// 访问Vue实例
const app = document.querySelector('#app').__vue_app__
// 访问Pinia store
import { useUserStore } from '@/store/modules/user'
const userStore = useUserStore()
console.log(userStore.userInfo)
// 访问路由
import { useRouter } from 'vue-router'
const router = useRouter()
console.log(router.currentRoute.value)6.2 Vue DevTools
安装Vue DevTools浏览器扩展:
- Chrome/Edge:Vue.js devtools
- Firefox:Vue.js devtools
Vue DevTools功能:
- 组件树:查看和调试Vue组件
- Vuex/Pinia:查看状态管理
- 事件:查看组件事件
- 性能:分析组件性能
6.3 网络请求调试
在浏览器开发者工具的Network面板中:
- 查看所有HTTP请求
- 查看请求和响应详情
- 查看请求头和响应头
- 查看请求和响应体
// 使用axios拦截器调试请求
axios.interceptors.request.use(config => {
console.log('请求配置', config)
return config
})
axios.interceptors.response.use(response => {
console.log('响应数据', response)
return response
})7. 性能调试
7.1 Performance面板
使用浏览器Performance面板分析性能:
- 打开开发者工具
- 切换到Performance面板
- 点击Record开始录制
- 执行需要分析的代码
- 点击Stop停止录制
- 分析性能数据
7.2 使用performance.now()
const measurePerformance = () => {
const start = performance.now()
// 执行需要测量的代码
for (let i = 0; i < 10000; i++) {
// ...
}
const end = performance.now()
const duration = end - start
Logger.prettyInfo('性能测试', `执行时间: ${duration.toFixed(2)}ms`)
}7.3 Chrome DevTools Performance
// 使用performance.mark()标记关键点
performance.mark('fetch-start')
const fetchData = async () => {
const res = await api.getData()
performance.mark('fetch-end')
performance.measure('fetch', 'fetch-start', 'fetch-end')
const measure = performance.getEntriesByName('fetch')[0]
Logger.prettyInfo('API性能', `耗时: ${measure.duration.toFixed(2)}ms`)
return res
}8. 常见调试场景
8.1 调试Vue组件
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import Logger from '@/utils/Logger'
const data = ref([])
onMounted(async () => {
Logger.prettyPrimary('组件挂载', '开始获取数据')
try {
const res = await api.getData()
data.value = res.data
Logger.prettySuccess('数据加载', '加载成功')
} catch (error) {
Logger.prettyError('数据加载', '加载失败')
console.error(error)
}
})
</script>8.2 调试Pinia Store
import { defineStore } from 'pinia'
import Logger from '@/utils/Logger'
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null as any
}),
actions: {
async getUserInfo() {
Logger.prettyPrimary('用户信息', '开始获取用户信息')
try {
const res = await api.getUserInfo()
this.userInfo = res.data
Logger.prettySuccess('用户信息', '获取成功')
Logger.print('success', this.userInfo)
} catch (error) {
Logger.prettyError('用户信息', '获取失败')
throw error
}
}
}
})8.3 调试路由
import { useRouter } from 'vue-router'
import Logger from '@/utils/Logger'
export default defineComponent({
setup() {
const router = useRouter()
const navigateTo = (path: string) => {
Logger.prettyPrimary('路由跳转', `跳转到: ${path}`)
router.push(path)
}
router.beforeEach((to, from, next) => {
Logger.prettyInfo('路由守卫', `从 ${from.path} 到 ${to.path}`)
next()
})
return { navigateTo }
}
})8.4 调试API请求
import axios from 'axios'
import Logger from '@/utils/Logger'
const api = axios.create({
baseURL: import.meta.env.VITE_BASE_URL
})
// 请求拦截器
api.interceptors.request.use(config => {
Logger.prettyPrimary('API请求', `${config.method?.toUpperCase()} ${config.url}`)
Logger.print('info', config.data)
return config
})
// 响应拦截器
api.interceptors.response.use(
response => {
Logger.prettySuccess('API响应', `${response.config.url}`)
Logger.print('success', response.data)
return response
},
error => {
Logger.prettyError('API错误', `${error.config?.url}`)
Logger.print('error', error.response?.data)
return Promise.reject(error)
}
)9. 调试技巧
9.1 使用debugger语句
在代码中插入debugger语句,浏览器会自动暂停:
const processData = (data: any) => {
debugger // 浏览器会在这里暂停
const result = data.map(item => item.value)
return result
}9.2 使用console.table()
使用表格形式输出数组或对象:
const users = [
{ name: '张三', age: 25 },
{ name: '李四', age: 30 },
{ name: '王五', age: 28 }
]
console.table(users)9.3 使用console.group()
将相关日志分组显示:
console.group('用户信息')
console.log('姓名:', user.name)
console.log('年龄:', user.age)
console.log('邮箱:', user.email)
console.groupEnd()9.4 使用console.time()
测量代码执行时间:
console.time('数据处理')
// 执行代码
const result = processData(data)
console.timeEnd('数据处理')9.5 使用console.trace()
追踪函数调用栈:
function functionA() {
functionB()
}
function functionB() {
console.trace('调用栈')
}
functionA()10. 常见问题
10.1 断点不生效
问题原因:
- Source Map未启用
- 代码被压缩
- 浏览器缓存
解决方案:
# 确保启用Source Map
# .env.local
VITE_SOURCEMAP=true
# 清除浏览器缓存
# 在开发者工具中右键刷新按钮,选择"清空缓存并硬性重新加载"10.2 TypeScript类型错误
问题原因:
- TypeScript配置不正确
- 类型定义缺失
解决方案:
// 检查tsconfig.json配置
{
"compilerOptions": {
"strict": true,
"sourceMap": true,
// ...
}
}
// 使用类型断言
const data = response.data as DataType
// 使用类型守卫
if (isTypeA(data)) {
// data在这里是TypeA类型
}10.3 Vue组件调试困难
问题原因:
- 组件嵌套过深
- 状态管理复杂
解决方案:
// 使用Vue DevTools
// 1. 安装Vue DevTools扩展
// 2. 在开发者工具中查看组件树
// 3. 查看组件的props、data、computed等
// 在组件中添加调试信息
export default defineComponent({
setup() {
const state = reactive({
count: 0
})
// 使用watch监听状态变化
watch(() => state.count, (newVal, oldVal) => {
Logger.prettyInfo('状态变化', `count: ${oldVal} -> ${newVal}`)
})
return { state }
}
})10.4 性能问题定位
问题原因:
- 组件频繁重新渲染
- 大量DOM操作
- 内存泄漏
解决方案:
// 使用Vue DevTools的Performance面板
// 1. 打开Performance面板
// 2. 点击Record开始录制
// 3. 执行操作
// 4. 停止录制并分析
// 使用performance API
const measureComponentRender = () => {
performance.mark('render-start')
// 组件渲染代码
performance.mark('render-end')
performance.measure('render', 'render-start', 'render-end')
const measure = performance.getEntriesByName('render')[0]
if (measure.duration > 100) {
Logger.prettyWarn('性能警告', `渲染耗时: ${measure.duration.toFixed(2)}ms`)
}
}11. 最佳实践
11.1 调试日志规范
- 使用Logger工具而不是console
- 生产环境移除调试代码
- 使用合适的日志级别
// 推荐
Logger.prettySuccess('操作成功', '数据保存成功')
// 不推荐
console.log('数据保存成功')11.2 断点使用规范
- 避免在生产代码中留下断点
- 使用条件断点减少中断
- 及时清理不需要的断点
11.3 性能监控
- 关键路径添加性能监控
- 定期分析性能数据
- 优化性能瓶颈
// 添加性能监控
const withPerformanceMonitor = async (name: string, fn: () => Promise<any>) => {
const start = performance.now()
try {
const result = await fn()
const duration = performance.now() - start
if (duration > 1000) {
Logger.prettyWarn('性能监控', `${name} 耗时: ${duration.toFixed(2)}ms`)
} else {
Logger.prettyInfo('性能监控', `${name} 耗时: ${duration.toFixed(2)}ms`)
}
return result
} catch (error) {
Logger.prettyError('性能监控', `${name} 执行失败`)
throw error
}
}
// 使用
const result = await withPerformanceMonitor('数据获取', () => api.getData())11.4 错误处理
- 使用try-catch捕获错误
- 记录详细的错误信息
- 提供友好的错误提示
const safeExecute = async (fn: () => Promise<any>, fallback?: any) => {
try {
return await fn()
} catch (error) {
Logger.prettyError('执行错误', error.message)
Logger.print('error', error)
if (fallback !== undefined) {
return fallback
}
throw error
}
}
// 使用
const result = await safeExecute(
() => api.getData(),
{ list: [], total: 0 }
)注意:本文档持续更新中,如有问题请及时反馈。
