codemirror 插件使用总结

最近工作中需要用到网页端代码编辑器。在此使用code-mirror插件作为提供者,以下总结一些遇到的问题及解决方案:
参考手册:
vue-codemirror 地址: https://github.com/codemirror/CodeMirror.
codemirror 中文API文档:https://olindk.gitbooks.io/codemirror/content/commands.html

描述
cm 以下cm皆为code-mirror简称
以下…皆为代码省略

1.无法自动加载配置文件,必须要点击一下code-mirror区域方可加载

  • 点击前
    在这里插入图片描述

  • 点击后:
    codemirror 插件使用总结_第1张图片

  • 解决方案:
    抓包后发现数据已经获取,猜测是cm没有执行自动刷新组件导致,在option内添加autoRefresh: true

    import 'codemirror/addon/display/autoRefresh.js'
    
    cmOptions: {
    	theme: 'xml',
    	mode: '',
    	readOnly: false,
    	autoRefresh: true,
    	autofocus: true,
    	viewportMargin: 1000, //指定当前滚动到视图中内容上⽅和下⽅要渲染的⾏数
    	lineNumbers: true, // 是否显示行号
        lineWrapping: true // 是否应滚动或换行以显示长行
    }
    

2.code-mirror和tab组件一起使用时,导致行号区域重叠

  • 异常时:
    codemirror 插件使用总结_第2张图片

  • 解决方案:
    点击切换tab时,需要刷新cm组件,否则有一定几率会造成行号区域重叠

    handleClick(tab, event){
    	 if (tab.name === 'selfDefineBtn') {
    	 	this.open(tab.index)
    	 } else {
    	 	this.$nextTick(() => {
    	 		// refresh code-mirror
    	     	let that = this.$refs.[this.activeName + 'mirror'][0].editor
    	     	that.refresh();
    	   	})
    	 }
    }
    
  • 解决后:
    codemirror 插件使用总结_第3张图片

3.code-mirror 组件中自定义方法
由于业务规则问题,保存配置文件时,会检测配置内容是否符合规则,若存在无法识别的语法则会提示错误信息并返回错误行号。

需要根据错误行号在textarea区域高亮显示错误行

cm组件内部已经考虑到了这点,提供了CodeMirror.defineExtension接口实现自定义的方法。

参考active-line高亮插件的原理,传入行号(from, to),实现高亮效果,贴上代码:

  • active-line 部分源代码:
    var WRAP_CLASS = "CodeMirror-activeline";
    var BACK_CLASS = "CodeMirror-activeline-background";
    var GUTT_CLASS = "CodeMirror-activeline-gutter";
    
    CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
      	...
      function clearActiveLines(cm) {
        for (var i = 0; i < cm.state.activeLines.length; i++) {
          cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
          cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
          cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_CLASS);
        }
      }
      function updateActiveLines(cm, ranges) {
        var active = [];
        ...
        cm.operation(function() {
          clearActiveLines(cm);
          for (var i = 0; i < active.length; i++) {
            cm.addLineClass(active[i], "wrap", WRAP_CLASS);
            cm.addLineClass(active[i], "background", BACK_CLASS);
            cm.addLineClass(active[i], "gutter", GUTT_CLASS);
          }
          cm.state.activeLines = active;
        });
      }
    });
    
  • 自定义新增方法:
    var WRAP_ERROR_CLASS = "CodeMirror-error-activeline";
    var BACK_ERROR_CLASS = "CodeMirror-error-activeline-background";
    var GUTT_ERROR_CLASS = "CodeMirror-error-activeline-gutter";
    
    CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
      	...
      //添加监听器,焦点在错误行时取消错误高亮样式
      cm.on("beforeSelectionChange", clearErrorLines);
      
      function clearAllActiveLines(cm) {
        clearActiveLines(cm);
        clearErrorLines(cm);
      }
      function clearErrorLines(cm) {
        for (var i = 0; i < cm.state.activeLines.length; i++) {
          cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_ERROR_CLASS );
          cm.removeLineClass(cm.state.activeLines[i], "background", BACK_ERROR_CLASS );
          cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_ERROR_CLASS );
        }
      }
    
      function updateActiveLines(cm, ranges) {...}
      
      /**
      * from: start line
      * to:   end line
      */
      const setErrorLines = function(cm, from, to) {
    	  let active = []
    	  if (!from || !to) return
    	  clearAllActiveLines(cm);
    	  for (let i = from; i <= to; i++) {
    	    let line = cm.getLineHandleVisualStart(i);
    	    this.addLineClass(line, "wrap", WRAP_ERROR_CLASS );
    	    this.addLineClass(line, "background", BACK_ERROR_CLASS );
    	    this.addLineClass(line, "gutter", GUTT_ERROR_CLASS );
    	  }
    	  cm.state.activeLines = active;
      };
      // 自定义方法
      CodeMirror.defineExtension("setErrorLines", setErrorLines);
    });
    
  • 效果展示:
    codemirror 插件使用总结_第4张图片

4.自动补全括号,且光标在括号左右侧时,自动突出匹配的括号

import 'codemirror/addon/edit/matchbrackets'
import 'codemirror/addon/edit/closebrackets'
cmOptions: {
	theme: 'xml',
	mode: '',
	readOnly: false,
	autoRefresh: true,
	autofocus: true,
	viewportMargin: 1000, //指定当前滚动到视图中内容上⽅和下⽅要渲染的⾏数
	lineNumbers: true, // 是否显示行号
    lineWrapping: true, // 是否应滚动或换行以显示长行
	autoCloseBrackets: true, // 自动闭合符号
	matchBrackets: true, // 在光标点击紧挨{、]括号左、右侧时,自动突出显示匹配的括号 }、]
}

后续出现问题还会继续补充

仅作为使用总结记录,望诸君共勉

你可能感兴趣的:(vue,前端,javascript,vue.js)