实现xml,json,sql代码组件格式化高亮:
需要下载的依赖:
<template><div class="box"><div class="top" v-if="flag"><span class="text">Theme:</span><el-select v-model="defaultOptions.theme" placeholder="请选择编辑器主题" class="select" @change="changeTheme"><el-option v-for="(theme, index) in themes" :key="index" :label="theme.label":value="theme.value"></el-option></el-select><span class="text">Language:</span><el-select v-model="defaultOptions.language" placeholder="请选择格式化语言" class="select"><el-option v-for="(item, index) in languageList" :key="index" :label="item.label" :value="item.value"></el-option></el-select><el-button type="primary" plain class="btn" @click="formatCode">格式化</el-button><el-button type="primary" plain class="btn" @click="clearSelection">清空</el-button></div><div :style="{ height, width }" :id="`monacoEditorContainer${index}`" class="container" @mouseleave="handleValue"></div></div>
</template><script>
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
import 'monaco-editor/esm/vs/editor/contrib/folding/folding.js';
// 代码高亮(将所有支持的语言全部显示)
import 'monaco-editor/esm/vs/basic-languages/monaco.contribution'
import { format } from 'sql-formatter';
import prettyData from 'pretty-data/pretty-data';
// 用于xml语法校验
import xml2js from 'xml2js';export default {props: {flag: { //顶部按钮是否显示type: Boolean,default: true},options: {type: Object,default: () => {}},code: {type: String,},height: {type: String,default: '90%'},width: {type: String,default: '100%'},index: {type: String,default: "01"},},data() {return {defaultOptions: {value: '', // 编辑器的值language: 'xml', //语言folding: true, // 是否折叠theme: 'vs-dark', // 编辑器主题:vs, hc-black, or vs-darkautoIndent: true, // 自动缩进wordWrap: 'on', // 启用自动换行readOnly: false, // 是否只读},languageList: [{ value: 'sql', label: 'SQL' },{ value: 'javascript', label: 'JSON' },{ value: 'xml', label: 'XML' },],themes: [{ value: 'vs', label: 'vs' },{ value: 'vs-dark', label: 'vs-dark' },{ value: 'hc-black', label: 'hc-black' }],monacoEditor: null};},mounted() {this.createMonacoEditor();},watch: {options: {handler() {this.$nextTick(() => {this.monacoEditor.updateOptions(this.standaloneEditorConstructionOptions)})},deep: true},code: {handler(newCode) {this.$nextTick(() => {// 将新数据显示在monacoEditor上this.monacoEditor.setValue(newCode);this.formatCode();});},deep: true,immediate: true,}},computed: {standaloneEditorConstructionOptions() {const options = Object.assign(this.defaultOptions, this.options);if (options.language.toUpperCase() === "JSON") {options.language = "javascript";}return options;}},methods: {formatCode() {const code = this.monacoEditor.getValue();if (!code.trim() || !this.defaultOptions.language) {// 值为空或者语言为空,不执行格式化操作return;}let formattedCode;switch (this.defaultOptions.language) {case 'sql':formattedCode = format(code);break;case 'javascript':try {JSON.parse(code); formattedCode = prettyData.pd.json(code);} catch (error) {this.$message.error(`JSON 解析错误: ${error}`);return;}break;case 'xml':try {// 使用 xml2js 库进行 XML 校验const parser = new xml2js.Parser();parser.parseString(code, (error) => {if (error) {this.$message.error(`XML 解析错误: ${error}`);// Message.error(`XML 解析错误: ${error}`);return;}});formattedCode = prettyData.pd.xml(code);} catch (error) {return;}break;default:return;}monaco.editor.setModelLanguage(this.monacoEditor.getModel(), this.defaultOptions.language);const model = this.monacoEditor.getModel();const formattedContent = {range: model.getFullModelRange(),text: formattedCode,};this.monacoEditor.executeEdits('format', [formattedContent]);},createMonacoEditor() {const container = document.getElementById(`monacoEditorContainer${this.index}`);this.monacoEditor = monaco.editor.create(container, this.standaloneEditorConstructionOptions);},clearSelection() {this.monacoEditor.setValue('');},changeTheme() {monaco.editor.setTheme(this.defaultOptions.theme);},handleValue() { this.formatCode();this.$emit('getValue', this.monacoEditor.getValue())// 鼠标失去焦点document.activeElement.blur();},},
};
</script><style scoped lang="less">
.box {width: 100%;height: 100%;.top {margin-bottom: 10px;.text {margin-right: 4px;}.btn {margin-right: 20px;margin-left: 0px;}.select {width: 200px!important;margin-right: 20px;}}.container {// width: 100%;// height: 90%;// margin-top: 20px;}
}
</style>
实现效果: