一.页面样式:
二、组件代码:
首先建一个vue页面放到components\CodeEditor 目录下 index.vue
把下面代码放入期中
<script setup>
// 导入monaco编辑器
import * as monaco from "monaco-editor";
import { ref, onMounted, onUnmounted, watch, nextTick, toRaw } from "vue";
const props = defineProps({
modelValue: {
type: String,
default: "",
},
language: {
type: String,
default: "javascript",
},
height: {
type: Number,
default: 300,
},
theme: {
type: String,
default: "vs-dark",
},
});
const emit = defineEmits(["update:modelValue", "change"]);
// 编辑器容器div
const editorContainer = ref(null);
// 编辑器实列
const editor = ref(null);
let isInternalChange = false;
const isMaximized = ref(false);
const originalHeight = ref(props.height);
// 切换主题
const switchTheme = (themeName) => {
if (editor.value) {
const rawEditor = toRaw(editor.value);
monaco.editor.setTheme(themeName);
}
};
// 切换最大化状态
const toggleMaximize = () => {
isMaximized.value = !isMaximized.value;
if (editor.value) {
const rawEditor = toRaw(editor.value);
nextTick(() => {
rawEditor.layout();
});
}
};
// 监听主题变化
watch(
() => props.theme,
(newTheme) => {
switchTheme(newTheme);
}
);
// 初始化编辑器
onMounted(async () => {
await nextTick();
if (editorContainer.value) {
const rawContainer = toRaw(editorContainer.value);
editor.value = monaco.editor.create(rawContainer, {
value: props.modelValue,
language: props.language,
theme: props.theme,
automaticLayout: true,
minimap: { enabled: false },
scrollBeyondLastLine: false,
fontSize: 14,
tabSize: 2,
formatOnPaste: true,
formatOnType: false,
suggestOnTriggerCharacters: false,
snippetSuggestions: "none",
wordWrap: "on",
renderWhitespace: "none",
overviewRulerBorder: false,
scrollBeyondLastColumn: 0,
renderLineHighlight: "none",
hideCursorInOverviewRuler: true,
lineNumbers: "on",
glyphMargin: false,
folding: true,
lineDecorationsWidth: 0,
lineNumbersMinChars: 3,
});
const rawEditor = toRaw(editor.value);
rawEditor.onDidChangeModelContent(() => {
if (!isInternalChange) {
const value = rawEditor.getValue();
emit("update:modelValue", value);
emit("change", value);
}
});
// 确保编辑器布局正确
setTimeout(() => {
const rawEditor = toRaw(editor.value);
rawEditor?.layout();
}, 100);
}
});
// 监听 modelValue 的变化
watch(
() => props.modelValue,
(newValue) => {
if (editor.value) {
const rawEditor = toRaw(editor.value);
if (newValue !== rawEditor.getValue()) {
isInternalChange = true;
rawEditor.setValue(newValue);
isInternalChange = false;
}
}
}
);
// 当组件被卸载时调用该回调函数
onUnmounted(() => {
if (editor.value) {
const rawEditor = toRaw(editor.value);
rawEditor.dispose();
}
});
// 暴露方法给父组件
defineExpose({
switchTheme,
toggleMaximize,
});
</script>
<template>
<div class="code-editor-container" :class="{ 'is-maximized': isMaximized }">
<div class="editor-toolbar">
<el-button-group>
<el-button size="small" @click="switchTheme('vs')">浅色</el-button>
<el-button size="small" @click="switchTheme('vs-dark')">深色</el-button>
</el-button-group>
<el-button size="small" @click="toggleMaximize">
<el-icon
><full-screen v-if="!isMaximized" /><scale-to-original v-else
/></el-icon>
</el-button>
</div>
<div
ref="editorContainer"
:style="{
height: isMaximized ? 'calc(100vh - 120px)' : `${height}px`,
transition: 'height 0.3s',
}"
></div>
</div>
</template>
<style scoped>
.code-editor-container {
position: relative;
width: 100%;
}
.code-editor-container.is-maximized {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2000;
background: var(--el-bg-color);
padding: 20px;
}
.editor-toolbar {
margin-bottom: 8px;
display: flex;
justify-content: flex-end;
gap: 8px;
}
div[ref="editorContainer"] {
width: 100%;
border: 1px solid #dcdfe6;
border-radius: 4px;
}
</style>
三、如何使用上面建好的组件
在需要使用的页面,把这个组件添加进去
import CodeEditor from "@/components/CodeEditor/index.vue";
具体的使用:
<el-form-item label="Python代码" prop="pyCode">
<code-editor
v-model="form.pyCode"
:language="'python'"
:height="300"
@change="handlePyCodeChange"
/>
</el-form-item>
const data = reactive({
form: {
id: null,
skillName: null,
skillDesc: null,
status: null,
sitePkg: null,
pyCode: "",
inParam: "",
outParam: "",
remark: null,
},
rules: {
pyCode: [{ required: true, message: "请输入Python代码", trigger: "blur" }],
},
});
// Python 代码变更处理
const handlePyCodeChange = (value) => {
// 把 具体的内容传到上面的变量中
form.value.pyCode = value;
};