vue3 使用 monaco 编辑器卡顿问题解决
💥 可能原因一:createModel
频繁创建未限制数量#
每次打开新文件都会 createModel
,但 Monaco Editor 的模型数量多了会导致性能骤降,尤其是在文件大或内存有限的情况下。
虽然你在关闭时 dispose()
掉模型,但如果用户连续打开了很多文件又不关闭(或文件太大),仍然可能导致卡顿。
✅ 解决建议一:限制最大模型缓存数量(比如 10 个)#
const MAX_MODELS = 10;
const handleFileOpened = async (payload: FileSystemEventPayloads[FileSystemEvents.FILE_OPENED]) => {
try {
const path = payload.path;
currentFilePath.value = path;
// 有模型就直接用
if (fileModels.value.has(path)) {
const model = fileModels.value.get(path);
if (model && editor) {
editor.setModel(model);
}
return;
}
// 控制缓存数量,超过就清理最早的
if (fileModels.value.size >= MAX_MODELS) {
const firstKey = fileModels.value.keys().next().value;
const oldModel = fileModels.value.get(firstKey);
oldModel?.dispose();
fileModels.value.delete(firstKey);
}
// 获取文件内容
const fileName = path.split(/[\\/]/).pop() || '';
const dirPath = path.substring(0, path.length - fileName.length - 1);
const response = await getFileContent(dirPath, fileName);
const language = getLanguageByExtension(path);
const model = monaco.editor.createModel(response.content || '', language);
fileModels.value.set(path, model);
editor?.setModel(model);
} catch (error) {
console.error('加载文件内容失败:', error);
}
};
💥 可能原因二:编辑器自动布局开销高#
你启用了 automaticLayout: true
,这会在容器大小变化时频繁触发 layout()
,在打开多个标签页、切换等复杂场景下会带来性能问题。
✅ 解决建议二:关闭自动布局,手动触发 layout#
editor = monaco.editor.create(editorContainer.value, {
value: '',
language: 'javascript',
theme: 'vs-dark',
minimap: { enabled: true },
scrollBeyondLastLine: false,
fontSize: 14,
fontFamily: 'Menlo, Monaco, Consolas, "Courier New", monospace',
automaticLayout: false
});
// 在切换标签或窗口大小变化时手动调用
window.addEventListener('resize', () => {
editor?.layout();
});
💥 可能原因三:文件太大 + 编辑器没有优化配置#
Monaco 默认不限制加载的文件大小,如果用户点击了一个特别大的 .log
或 .json
文件,可能瞬间拖垮前端。
✅ 解决建议三:加载前做文件大小检查(从后端接口拿 size)#
if (response.size > 1024 * 1024 * 2) { // >2MB 警告或不打开
alert('文件太大,不建议在浏览器中打开');
return;
}
💥 可能原因四:Vue 的响应式系统拖慢了文件切换#
你用了 ref(Map)
,Vue 会对 Map 的一些操作做响应式处理,虽然现代 Vue 已经优化了不少,但也可能导致额外开销。
✅ 解决建议四:使用 shallowRef
代替 ref
#
import { shallowRef } from 'vue';
const fileModels = shallowRef(new Map<string, monaco.editor.ITextModel>());
🧪 你可以做一个简单测试:#
打开
5~10
个文件,观察内存和卡顿;注释掉
createModel
改成一个统一的共享 model 看看卡不卡;把
automaticLayout
改成 false 看是否缓解。
使用 shallowRef
代替 ref
解决问题#
本作品采用《CC 协议》,转载必须注明作者和本文链接