实现代码
<a-modal ref="formModal" :formData="formData" :rules="rules" width="1000" :label-col="{ span: 4 }"
@handle-ok="handleOk()">
<div class="container">
<div class="left-column">
<div class="params">
<div class="section-title">case输入</div>
<Codemirror v-model:value="formData.content" :options="cmOptions" border
:height="300" @ready="onEditorReady" />
</div>
<div class="request">
<div class="section-title">case期待输出</div>
<Codemirror v-model:value="formData.compare" :options="cmOptions" border
:height="280" @ready="(cm) => onEditorReady(cm, 'compare')" />
</div>
</div>
<div class="right-column">
<div class="response">
<div class="section-title">case接口返回</div>
<Codemirror v-model:value="formData.detail" :options="cmOptions" border
:height="630" @ready="(cm) => onEditorReady(cm, 'detail')" />
</div>
</div>
</div>
</a-modal>
// 编辑器尺寸变化处理
const setupEditorResize = (cmInstance, type) => {
let lastHeight = cmInstance.getWrapperElement().offsetHeight;
const resizeObserver = new ResizeObserver(([entry]) => {
const { height } = entry.contentRect;
if (height !== lastHeight) {
cmInstance.refresh();
if (type === 'compare') {
highlightErrors(cmInstance, mismatchedLeft.value);
} else if (type === 'detail') {
highlightErrors(cmInstance, mismatchedRight.value);
const lineNumber = mismatchedRight.value[0]?.line - 2 || 0;
cmInstance.scrollTo(0, cmInstance.charCoords({ line: lineNumber, ch: 0 }, 'local').top);
}
}
lastHeight = height;
});
resizeObserver.observe(cmInstance.getWrapperElement());
return resizeObserver;
};
// 编辑器准备就绪回调
const onEditorReady = (cmInstance, type = 'content') => {
observer.value = setupEditorResize(cmInstance, type);
};
// 组件卸载时清理observer
onUnmounted(() => observer.value.disconnect());
排查问题步骤
1.渲染流程分析:Modal开始渲染 -> Modal执行打开动画 -> CodeMirror 组件初始化 -> CodeMirror 计算尺寸和布局 -> CodeMirror 渲染编辑器内容和行号
const onCompareReady = (cmInstance) => {
console.log('Initial state:', {
// modal是否显示
modalVisible: formModal.value?.visible,
// 容器的宽度
containerWidth: cmInstance.getWrapperElement().offsetWidth,
// 容器的高度
containerHeight: cmInstance.getWrapperElement().offsetHeight,
// 滚动信息
scrollInfo: cmInstance.getScrollInfo(),
// 总行数
lineCount: cmInstance.lineCount(),
// 行号区域的宽度
gutterWidth: cmInstance.getGutterElement().offsetWidth
});
// 监听尺寸变化
const resizeObserver = new ResizeObserver((entries) => {
console.log('Size changed:', {
width: entries[0].contentRect.width,
height: entries[0].contentRect.height,
time: Date.now()
});
});
resizeObserver.observe(cmInstance.getWrapperElement());
};
2.发现初始的高度过高,编辑器的高度会重新渲染。
- 可能得原因是Modal 动画过程中容器尺寸不稳定
- CodeMirror 的初始化时机过早
- 行号计算依赖于准确的容器尺寸
- 浏览器的重排和重绘时序问题