vue3插件:ace-builds封装ace-editor

安装包

npm install ace-builds --save-dev
//引入ace报错需要安装
npm install vue-loader-v16 -D

封装文件

ace-editor相关文档参考

webpack环境必备:import "ace-builds/webpack-resolver";
非webpack环境不需要引入

<template>
  <div ref="editorform" style="height: 300px" class="ace-editor"></div>
</template>
<script>
import { watch, onMounted, onBeforeUnmount, ref} from "vue";
import ace from "ace-builds";
import "ace-builds/webpack-resolver";
import "ace-builds/src-noconflict/mode-yaml";
import "ace-builds/src-noconflict/theme-chaos";
import "ace-builds/src-noconflict/ext-language_tools";
import "ace-builds/src-noconflict/ext-emmet";
import "ace-builds/src-noconflict/snippets/yaml";
//import "ace-builds/src-noconflict/keybinding-vscode";
//import "ace-builds/src-noconflict/keybinding-emacs";
export default {
  name: "CodeEditor",
  emits: ["update:value"],
  props: {
    id: {
      type: Number,
      default: 0,
    },
    // 外部传入的内容,用于实现双向绑定
    value: {
      type: String,
      default: "",
    },
    readonly: {
      type: Boolean,
      default: false,
    },
    // 外部传入的语法类型
    language: {
      type: String,
      default: "yaml",
    },
    // 编辑器主题色
    theme: {
      type: String,
      default: "chaos",
    },
  },
  setup(props, { emit }) {
    let editor = null;
    const editorform = ref(null);
    let options = {
      theme: "ace/theme/" + (props.theme ? props.theme : "chaos"),
      mode: "ace/mode/" + (props.language ? props.language : "yaml"),
      tabSize: 2,
      maxLines: 25,
      minLines: 25,
      showPrintMargin: false,
      fontSize: 14,
      readOnly: props.readonly ? props.readonly : false,
    };
    //切换语言
    //editor.getSession().setMode(modelPath)

    function initialize() {
      if (editor) {
        //实例销毁
        editor.destroy();
      }
      //初始化
      editor = ace.edit(editorform.value, options);
      //代码提示和自动补全
      editor.setOptions({
        enableSnippets: true,
        enableLiveAutocompletion: true,
        enableBasicAutocompletion: true,
      });
      editor.getSession().setUseWrapMode(true);
      // 支持双向绑定
      editor.on("change", () => {
        if (emit) {
          emit("update:value", editor.getValue());
        }
      });
       //快捷键
      editor.commands.addCommand({
        name: 'formatter',
        bindKey: { win: 'Ctrl-Shift-F', mac: 'Command-Shift-F' },
        exec: () => emit('formatter', editor)
      })
      editor.setValue(props.value ? props.value : "");
    }
    watch(
      () => props.id,
      () => {
        initialize();
      }
    );
    watch(
      () => props.value,
      (newProps) => {
        //解决光标移动问题
        const position = editor.getCursorPosition();
        editor.getSession().setValue(newProps);
        editor.clearSelection();
        editor.moveCursorToPosition(position);
      }
    );
    onMounted(() => {
      initialize();
    });
    onBeforeUnmount(() => {
      editor.destroy();
    });
    return {
      editorform,
    };
  },
};
</script>
<style lang="scss" scoped>
    .ace-chaos .ace_meta.ace_tag{
        color:#53a7e6 !important;
    }
    .ace-chaos .ace_string{
        color:#c58854 !important;
    }
    .ace-chaos .ace_keyword{
        color:#e0e0e0 !important;
    }
    .ace-chaos .ace_constant.ace_numeric{
        color:#c5c454 !important;
    }
</style>

###页面使用

<!--解决视图更新问题-->
<!--@update:value="cmadd.value = $event"-->
<template>
<div>
  <code-editor
        ref="addcodeform"
        v-model:value="cmadd.value"
        v-model:id="cmadd.id"
        @update:value="cmadd.value = $event"
      ></code-editor>
</div>
</template>
<script>
import {ref} from "vue";
import CodeEditor from "@/components/AceEditor";
export default {
  components:{CodeEditor},
  setup(){
    const cmadd=ref({value:"",id:0});
    return{cmadd}
  }
}
</script>