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);
};

实现效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值