Bootstrap

Vue使用monaco-editor代码编辑器组件(查找定位,代码高亮,自定义右键,各种监听事件)

Vue使用monaco-editor组件

安装初始化项目

// 使用的稳定版本配套
cnpm install monaco-editor@0.30.1
cnpm install monaco-editor-webpack-plugin@6.0.0

vue.config.js

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
...
plugins: [
    new MonacoWebpackPlugin()
]

在组件中进行使用

<template>
  <div ref="editorContainer" class="editor"></div>
</template>

<script>
    import * as monaco from 'monaco-editor'
    export default {
        name: 'MonacoEditor',
    },
    data() {
        return {
          code: '',
          editor: null,
        }
    },
    mounted() {
        this.init()
    },
    methods: {
        init(){
          // 初始化编辑器
          this.editor = monaco.editor.create(this.$refs.editorContainer, {
            value: this.code,
            language: 'java',
            tabSize: 2,
            theme: 'vs-dark',
            minimap: {
              enabled: false// 关闭小地图
            },
            scrollBeyondLastLine: false,
            automaticLayout: true, // 自动布局
            readOnly: false //只读
          })
        }
    }
  },
</script>

进阶用法

monaco-editor查找字符并定位

findStringAndMoveTo(string) { // 代码编辑器锁定到第几行
  const model = this.editor.getModel()
  const range = model.findMatches(string, false, true, false, null, true)[0].range
  if (range) {
    // 这里的+17行原因是为了把代码行数移动到第一行,移除+17代码会定位显示到编辑器的中间部分
    this.editor.revealLineInCenterIfOutsideViewport(range.startLineNumber + 17, 0)
    this.editor.setPosition({ lineNumber: range.startLineNumber, column: range.startColumn })
    this.editor.focus()
  }
}

monaco-editor设置代码高亮

// 注意在每次更新代码后都要执行此方法,刷新格式
initColor() {
  this.color = monaco.languages.setMonarchTokensProvider('java', {
    ignoreCase: true,
    tokenizer: {//需要什么颜色,就在里面用正则匹配
      root: [
        [
          /currentUser|#@|RsOk|#string|#switch|#case|selectSql|uuid|addOrderBy|addConditionRequired|countSql|platform|end_platform|receiver|end_receiver|mode|end_mode|hz|deg|true|terrain_and_horizon|db|kw|horizontal|bit|fixed|rpm|false|none|terrain_and_horizon|platform_type|end_platform_type|mode_template|end_mode_template |azimuth|elevation|both|azimuth_and_elevation|independent|mover|ft|end_mover|kg|meter|air|blue|red|coordinated|addGroupBy|currentDateTime|addFieldExist|formData|simplePage |RsJson|@]|RsJsonData|Local|select|#set|#include|#render|#end|#for|#if|#else|#elseif|from|where|addField|addConditionExist|table|SqlUtil| GROUP_CONCAT|BY|AND|ADD|Data|page|IF|as|SUM|MAX|min|AVG|COUNT|ROUND|LEFT|JOIN/,
          { token: 'keyword' }
        ], //蓝色
        [
          /[+]|[-]|[*]|[/]|[%]|[>]|[<]|[=]|[!]|[:]|[&&]|[||]/,
          { token: 'string' }
        ], //红色
        [/'.*?'|".*?"/, { token: 'string.escape' }], //橙色
        [/#--.*?--#|-|1|2|3|4|5|6|7|8|9|0|1.0|2|WSF_ACOUSTIC_SENSOR|WSF_PLATFORM|WSF_AIR_MOVER/, { token: 'comment' }], //绿色
        [/null/, { token: 'regexp' }], //粉色
        [/[{]|[}]/, { token: 'type' }], //青色
        // [/[\u4e00-\u9fa5]/, { token: 'predefined' }],//亮粉色
        // [/''/, { token: 'invalid' }],//红色
        // [/[\u4e00-\u9fa5]/, { token: 'number.binary' }],//浅绿
        [/(?!.*[a-zA-Z])[0-9]/, { token: 'number.hex' }], //浅绿
        [/[(]|[)]/, { token: 'number.octal' }], //浅绿
        // [/[\u4e00-\u9fa5]/, { token: 'number.float' }],//浅绿
      ]
    },
  })
},

monaco-editor自定义右键

this.editor.addAction({
    id: 'file_formatter',
    label: '自定义右键', // 菜单名称
    keybindings: [monaco.KeyMod.Shift | monaco.KeyMod.Alt | monaco.KeyCode.KEY_F], // 快捷键
    contextMenuGroupId: 'code_formatter',
    run: () => {
      console.log('自定义', this.editor.getValue())
    }
  })

monaco-editor切换代码显示

// 因为monaco-editor并不会双向绑定this.code,所以this.code发生变化后需要手动设置代码
const newModel = monaco.editor.createModel(
            this.code,
            'java'
          )
this.initColor()
this.editor.setModel(newModel)

monaco-editor监听内容变化

this.editor.onDidChangeModelContent(() => {
    ...
})

monaco-editor监听失去焦点事件

this.editor.onDidBlurEditorText((e) => {
    ...
})

monaco-editor监听编辑输出当前光标所在行数和列数等数据

this.editor.onDidChangeCursorPosition((event) => {
    if (event.position && event.position.lineNumber === 5) {
      console.log('当前光标所在行数为第五行')
      // 输出该行的代码
      const lineContent = this.editor.getModel().getValueInRange({
        startLineNumber: event.position.lineNumber,
        endLineNumber: event.position.lineNumber + 1,
        startColumn: 0,
        endColumn: Number.MAX_VALUE
      })
      console.log(`${event.position.lineNumber}行的代码为:\n`, lineContent)
    }
})
;