vue-codemirror代码编辑器使用

初晴wxy / 2024-06-06 / 原文

参考链接:vue2 导入使用vue-codemirror详解-CSDN博客

1.安装 vue-codemirror

npm i vue-codemirror

// codemirror 需要与 vue-codemirror 同时安装

npm i codemirror

2.使用codemirror组件

<template>
  <div class="code-box">
    <codemirror
      ref="codeMirror"
      v-model="cmContent"
      :options="cmOptions"
      @ready="onCmReady"
      @blur="onCmBlur"
    />
  </div>
</template>

<script>
import { codemirror } from 'vue-codemirror';
// 引入主题和功能
import './theme';
// 引入jshint
import jshint from 'jshint';

export default {
  name: 'PluginCode',
  components: { codemirror },
  props: {
    code: {
      type: String,
      default: ''
    },
    fullScreen: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      cmContent: this.code,
      cmOptions: {
        // Config配置
        mode: 'text/javascript', // 模式
        theme: 'idea', // 主题
        indentUnit: 2, // 缩进位数
        smartIndent: true, // 智能缩进
        tabSize: 4, // 制表符
        lineWrapping: true, // 自动换行
        lineNumbers: true, // 显示行号
        lint: { 'esversion': '6' }, //  语法提示
        readOnly: false, // 是否只读
        lineWiseCopyCut: true, // 复制或剪切时没有选择文本,那么自动选光标所在整行
        spellcheck: true, // 拼写检查
        autocorrect: true, // 自动补全
        autofocus: false, // 是否在初始化时自动获取焦点
        showCursorWhenSelecting: true, // 光标选中效果
        gutters: ['CodeMirror-lint-markers', 'CodeMirror-linenumbers', 'CodeMirror-foldgutter'], // gutter的CSS配置
        extraKeys: {
          Tab: (cm) => {
            if (cm.somethingSelected()) {
              // 正向缩进文本
              cm.indentSelection('add');
            } else {
              // 光标处插入 indentUnit 个空格
              cm.replaceSelection(Array(cm.getOption('indentUnit') + 1).join(' '), 'end', '+input');
            }
          },
          Esc: (cm) => {
            cm.setOption('fullScreen', false);
            this.$emit('update:fullScreen', false);
          },
          'Ctrl-S': (cm) => { cm.save(); },
          'Ctrl-/': 'toggleComment'
        },
        dragDrop: true, // 允许拖放文件和图片到编辑器里
        allowDropFileTypes: ['text/javascript'], // 默认为null。当设置此项时,只接收包含在此数组内的文件类型拖入编辑器
        viewportMargin: 1000, // 视图中内容上方和下方要渲染的行数
        // Addons配置
        foldGutter: true, // 启用行槽中的代码折叠
        matchBrackets: true, // 括号匹配
        autoCloseBrackets: true, // 自动闭合符号
        styleActiveLine: true, // 当前行背景高亮
        styleSelectedText: true, // 高亮选中文字
        hintOptions: { completeSingle: false } // 当匹配只有一项时, 是否自动补全
      }
    };
  },
  computed: {
    cm() {
      return this.$refs.codeMirror.codemirror;
    }
  },
  watch: {
    code: {
      handler(val) {
        if (val) this.cmContent = val;
      },
      immediate: true
    },
    fullScreen: {
      handler(val) {
        if (val) {
          this.cm.setOption('fullScreen', !this.cm.getOption('fullScreen'));
          this.cm.focus();
          // 设置焦点在内容尾部
          this.cm.setCursor(this.cm.lineCount(), 0);
        }
      },
      immediate: true
    }
  },
  beforeCreate() {
    window.JSHINT = jshint.JSHINT;
  },
  beforeDestroy() {
    this.$refs.codeMirror = null;
  },
  mounted() {},
  methods: {
    // 加载事件
    onCmReady(cm) {
      // 这里的 cm 对象就是 codemirror 对象,等于 this.$refs.codeMirror.codemirror
      cm.on('inputRead', (cm, obj) => {
        if (obj.text && obj.text.length > 0) {
          const c = obj.text[0].charAt(obj.text[0].length - 1);
          if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
            cm.showHint({ completeSingle: false });
          }
        }
      });
    },
    // 失去焦点
    onCmBlur() {
      this.$emit('getCmContent', this.cmContent);
    },
    // 校验错误
    onCmError(cm = this.cm) {
      const marked = cm?.state?.lint?.marked;
      if (marked?.length) {
        const markError = marked.filter(m => m.className.includes('mark-error'));
        if (markError?.length) {
          // 设置焦点在错误位置
          const item = markError[0]?.lines[0];
          if (item) {
            cm.focus();
            const line = cm.getLineNumber(item);
            cm.setCursor(line, item.text.length);
            this.$modal.msgWarning(`当前插件开发脚本存在语法错误, 已定位至错误位置`);
            return true;
          }
        }
      }
      return false;
    }
  }
};
</script>

<style scoped lang="scss">
::v-deep .CodeMirror {
  font-size: 14px;
  height: 350px;
  &.cm-s-idea {
    span.cm-def {
      color: #aa0000;
    }
  }
  &.CodeMirror-fullscreen {
    z-index: 9999;
  }
  .CodeMirror-activeline-background {
    background: #e8f2ff;
  }
  .CodeMirror-gutters {
    background: #F6F6F6;
  }
  .CodeMirror-hints {
    position: absolute;
    z-index: 10;
    overflow: hidden;
    list-style: none;
    margin: 0;
    padding: 2px;
    box-shadow: 2px 3px 5px rgba(0,0,0,.2);
    border-radius: 3px;
    border: 1px solid silver;
    background: white;
    font-size: 90%;
    font-family: monospace;
    max-height: 20em;
    overflow-y: auto;
  }
}
</style>
 
3.theme.js中引入样式
// 引入样式
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/idea.css';
// 引入语言
import 'codemirror/mode/javascript/javascript.js';
// 数据校验
import 'codemirror/addon/lint/lint.css';
import 'codemirror/addon/lint/lint.js';
import 'codemirror/addon/lint/javascript-lint.js';
// 代码折叠
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/fold/foldgutter.js';
import 'codemirror/addon/fold/foldcode.js';
import 'codemirror/addon/fold/brace-fold.js';
import 'codemirror/addon/fold/comment-fold.js';
import 'codemirror/addon/fold/indent-fold.js';
// 高亮选中
import 'codemirror/addon/selection/active-line.js';
import 'codemirror/addon/selection/mark-selection.js';
// 代码高亮
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/hint/show-hint.js';
import 'codemirror/addon/hint/javascript-hint.js';
import 'codemirror/addon/hint/anyword-hint.js';
// 代码注释
import 'codemirror/addon/comment/comment.js';
import 'codemirror/addon/comment/continuecomment.js';
// 自动括号
import 'codemirror/addon/edit/matchbrackets.js';
import 'codemirror/addon/edit/closebrackets.js';
// 代码全屏
import 'codemirror/addon/display/fullscreen.css';
import 'codemirror/addon/display/fullscreen.js';
// 滚动条
import 'codemirror/addon/scroll/simplescrollbars.css';
import 'codemirror/addon/scroll/simplescrollbars.js';
// // 提示弹窗
// import 'codemirror/addon/dialog/dialog.css';
// import 'codemirror/addon/dialog/dialog.js';
// // 搜索功能
// import 'codemirror/addon/search/search.js';
// import 'codemirror/addon/search/searchcursor.js';
// import 'codemirror/addon/search/jump-to-line.js';
// import 'codemirror/addon/search/match-highlighter.js';