vue3+ts json编辑器
//下载插件
"monaco-editor": "^0.30.1",
"monaco-editor-webpack-plugin": "^6.0.0"
yarn add monaco-editor@0.30.1
yarn add monaco-editor-webpack-plugin@6.0.0
src目录下创建 shims-vue.d.ts (ts的话需要创建该文件,不然会报模块引入错误)
//记得在env.d.ts配置包的
declare module 'monaco-editor';
declare module 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
declare module 'monaco-editor/esm/vs/basic-languages/sql/sql.js';
declare module 'monaco-editor/esm/vs/basic-languages/yaml/yaml.js';
declare module 'monaco-editor/esm/vs/language/json/json.worker?worker'
declare module 'monaco-editor/esm/vs/language/css/css.worker?worker'
declare module 'monaco-editor/esm/vs/language/html/html.worker?worker'
declare module 'monaco-editor/esm/vs/editor/editor.worker?worker'
declare module 'monaco-editor/esm/vs/basic-languages/javascript/javascript.js'
创建组件文件 monacoEditor.vue
<template>
<div ref="codeEditBox" class="codeEditBox" :class="hightChange && 'codeEditBox1'" />
</template>
<script lang="ts">
import { defineComponent, onBeforeUnmount, onMounted, ref, watch } from "vue";
import * as monaco from "monaco-editor";
import { language as sqlLanguage } from "monaco-editor/esm/vs/basic-languages/sql/sql.js";
import { language as yamlLanguage } from "monaco-editor/esm/vs/basic-languages/yaml/yaml.js";
import "monaco-editor/esm/vs/basic-languages/sql/sql.contribution";
import "monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution";
import "monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution";
import { editorProps } from "./monacoEditorType";
// import JsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
// import CssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
// import HtmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
// import TsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
// import EditorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
// import * as monaco from "monaco-editor";
// import { language as sqlLanguage } from "monaco-editor/esm/vs/basic-languages/sql/sql.js";
// import { language as yamlLanguage } from "monaco-editor/esm/vs/basic-languages/yaml/yaml.js";
// import "monaco-editor/esm/vs/basic-languages/sql/sql.contribution";
// import { editorProps } from "./monacoEditorType";
export default defineComponent({
name: "MonacoEditor",
props: editorProps,
emits: ["update:modelValue", "change", "editor-mounted"],
setup(props, { emit }) {
(self as any).MonacoEnvironment = {
getWorker: (_: string, label: string) => {
const getWorkerModule = (moduleUrl: string, label: string) =>
new Worker((self as any).MonacoEnvironment.getWorkerUrl(moduleUrl), {
name: label,
type: "module",
});
switch (label) {
case "json":
return getWorkerModule(
"/monaco-editor/esm/vs/language/json/json.worker?worker",
label
);
case "css":
case "scss":
case "less":
return getWorkerModule(
"/monaco-editor/esm/vs/language/css/css.worker?worker",
label
);
case "html":
case "handlebars":
case "razor":
return getWorkerModule(
"/monaco-editor/esm/vs/language/html/html.worker?worker",
label
);
case "typescript":
case "javascript":
return getWorkerModule(
"/monaco-editor/esm/vs/language/typescript/ts.worker?worker",
label
);
default:
return getWorkerModule(
"/monaco-editor/esm/vs/editor/editor.worker?worker",
label
);
}
},
// getWorker(_: string, label: string) {
// if (label === "json") {
// return new JsonWorker();
// }
// if (["css", "scss", "less"].includes(label)) {
// return new CssWorker();
// }
// if (["html", "handlebars", "razor"].includes(label)) {
// return new HtmlWorker();
// }
// if (["typescript", "javascript"].includes(label)) {
// return new TsWorker();
// }
// return new EditorWorker();
// },
};
let editor: any;
const codeEditBox = ref();
const init = () => {
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: true,
noSyntaxValidation: false,
});
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES2020,
allowNonTsExtensions: true,
});
monaco.languages.registerCompletionItemProvider("sql", {
provideCompletionItems() {
const suggestions: any = [];
// 这个keywords就是sql.js文件中有的
sqlLanguage.keywords.forEach((item: any) => {
suggestions.push({
label: item,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: item,
});
});
sqlLanguage.operators.forEach((item: any) => {
suggestions.push({
label: item,
kind: monaco.languages.CompletionItemKind.Operator,
insertText: item,
});
});
sqlLanguage.builtinFunctions.forEach((item: any) => {
suggestions.push({
label: item,
kind: monaco.languages.CompletionItemKind.Function,
insertText: item,
});
});
sqlLanguage.builtinVariables.forEach((item: any) => {
suggestions.push({
label: item,
kind: monaco.languages.CompletionItemKind.Variable,
insertText: item,
});
});
return {
// 最后要返回一个数组
suggestions,
};
},
});
monaco.languages.registerCompletionItemProvider("yaml", {
provideCompletionItems() {
const suggestions: any = [];
// 这个keywords就是python.js文件中有的
yamlLanguage.keywords.forEach((item: any) => {
suggestions.push({
label: item,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: item,
});
});
return {
// 最后要返回一个数组
suggestions,
};
},
});
editor = monaco.editor.create(codeEditBox.value, {
value: props.modelValue,
language: props.language,
readOnly: props.readOnly,
theme: props.theme,
...props.options,
});
// 监听值的变化
editor.onDidChangeModelContent(() => {
const value = editor.getValue(); // 给父组件实时返回最新文本
emit("update:modelValue", value);
emit("change", value);
});
emit("editor-mounted", editor);
};
watch(
() => props.modelValue,
(newValue) => {
if (editor) {
const value = editor.getValue();
if (newValue !== value) {
editor.setValue(newValue);
}
}
}
);
watch(
() => props.options,
(newValue) => {
editor.updateOptions(newValue);
},
{ deep: true }
);
watch(
() => props.readOnly,
() => {
console.log("props.readOnly", props.readOnly);
editor.updateOptions({ readOnly: props.readOnly });
},
{ deep: true }
);
watch(
() => props.language,
(newValue) => {
monaco.editor.setModelLanguage(editor.getModel()!, newValue);
}
);
onBeforeUnmount(() => {
editor.dispose();
});
onMounted(() => {
init();
});
return { codeEditBox };
},
});
</script>
<style scoped>
.codeEditBox {
height: 300px;
width: 100%;
flex: 1;
min-height: 100px;
overflow-y: auto;
}
.codeEditBox1 {
height: calc(100% - 323px);
}
</style>
创建组件实现方法ts monacoEditorType.ts
import { PropType } from 'vue'
export type Theme = 'vs' | 'hc-black' | 'vs-dark'
export type FoldingStrategy = 'auto' | 'indentation'
export type RenderLineHighlight = 'all' | 'line' | 'none' | 'gutter'
export interface Options {
automaticLayout: boolean // 自适应布局
foldingStrategy: FoldingStrategy // 折叠方式 auto | indentation
renderLineHighlight: RenderLineHighlight // 行亮
selectOnLineNumbers: boolean // 显示行号
placeholder: string
minimap: {
// 关闭小地图
enabled: boolean
}
// readOnly: Boolean // 只读
fontSize: number // 字体大小
scrollBeyondLastLine: boolean // 取消代码后面一大段空白
overviewRulerBorder: boolean // 不要滚动条的边框
}
export const editorProps = {
modelValue: {
type: String as PropType<string>,
default: null,
},
hightChange: {
type: Boolean,
default: false,
},
width: {
type: [String, Number] as PropType<string | number>,
default: '100%',
},
height: {
type: [String, Number] as PropType<string | number>,
default: '100%',
},
language: {
type: String as PropType<string>,
default: 'javascript',
},
readOnly: {
type: Boolean,
default: false,
},
theme: {
type: String as PropType<Theme>,
validator(value: string): boolean {
return ['vs', 'hc-black', 'vs-dark', 'hc-light'].includes(value)
},
default: 'vs',
},
options: {
type: Object as PropType<Options>,
default() {
return {
automaticLayout: true,
// foldingStrategy: 'indentation',
foldingStrategy: 'indentation', // 折叠方式 auto | indentation
// renderLineHighlight: 'all',
renderLineHighlight: 'all' || 'line' || 'none' || 'gutter', // 行亮
selectOnLineNumbers: true, // 显示行号
minimap: {
// 关闭小地图
enabled: true,
},
placeholder: 'ss',
// readOnly: false, // 只读
fontSize: 14, // 字体大小
scrollBeyondLastLine: false, // 取消代码后面一大段空白
overviewRulerBorder: false, // 不要滚动条的边框
}
},
},
}
使用方式
import monacoEditor from "/@/components/monaco/monacoEditor.vue";
<monacoEditor
v-model="formState.tablename"
:language="language"
:hight-change="hightChange"
width="100%"
height="60%"
:scrollerHeight="'calc(100% - 280px)'"
@editor-mounted="editorMounted"
/>
js部分变量声明
const language = ref("json");
const hightChange = ref<any>(false);
const editorMounted = (editor: any) => {
console.log("editor实例加载完成", editor);
};
实现效果
SailingCoder: 下载资源太慢了,这是啥情况
CSDN-Ada助手: 这篇博客非常实用,让我对vue3和ts有了更深入的了解,同时也学到了如何使用json编辑器。希望作者能够继续分享更多的技术文章,让我们一起进步!另外,对于json编辑器的相关知识,我们还可以深入学习json格式、json对象、json数组等内容,同时也可以了解一下类似于XML、YAML等格式化的数据存储方式。 如何写出更高质量的博客,请看该博主的分享:https://blog.csdn.net/lmy_520/article/details/128686434?utm_source=csdn_ai_ada_blog_reply2
小白前端1: vite的配置也要引入模块 optimizeDeps: { include: [ `monaco-editor/esm/vs/language/json/json.worker`, `monaco-editor/esm/vs/language/css/css.worker`, `monaco-editor/esm/vs/language/html/html.worker`, `monaco-editor/esm/vs/language/typescript/ts.worker`, `monaco-editor/esm/vs/editor/editor.worker` ], },
CSDN-Ada助手: 非常棒的第一篇博客!看到你对前端预览插件的总结和分享,让我受益匪浅。期待你未来更多的博客分享,为前端开发者带来更多价值。 推荐【每天值得看】:https://bbs.csdn.net/forums/csdnnews?typeId=21804&utm_source=csdn_ai_ada_blog_reply1