一、安装依赖

npm install editor@1.0.0
npm install monaco-editor@0.19.3
npm install monaco-editor-webpack-plugin@1.9.1

二、配置vue.config.js文件

没有vue.config.js的话就在根目录新建一个

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = {
  configureWebpack: {
    plugins: [
        new MonacoWebpackPlugin()
    ]
}

三、新增jsonpath.js

const colType = { Object, Array }

export function getJsonPath(text, offSet) {
    let pos = 0
    let stack = []
    let isInKey = false

    while (pos < offSet) {
        const startPos = pos
        switch (text[pos]) {
            case '"':
                const { text: s, pos: newPos } = readString(text, pos)
                if (stack.length) {
                    const frame = stack[stack.length - 1]
                    if (frame.colType === colType.Object && isInKey) {
                        frame.key = s
                        isInKey = false
                    }
                }
                pos = newPos
                break
            case '{':
                stack.push({ colType: colType.Object })
                isInKey = true
                break
            case '[':
                stack.push({ colType: colType.Array, index: 0 })
                break
            case '}':
            case ']':
                stack.pop()
                break
            case ',':
                if (stack.length) {
                    const frame = stack[stack.length - 1]
                    if (frame.colType === colType.Object) {
                        isInKey = true
                    } else {
                        frame.index++
                    }
                }
                break
        }
        if (pos === startPos) {
            pos++
        }
    }
    return pathToString(stack);
}

function pathToString(path) {
    let s = '$'
    try {
        for (const frame of path) {
            if (frame.colType === colType.Object) {
                if (!frame.key.match(/^[a-zA-Z$_][a-zA-Z\d$_]*$/)) {
                    const key = frame.key.replace('"', '\\"')
                    s += `["${frame.key}"]`
                } else {
                    if (s.length) {
                        s += '.'
                    }
                    s += frame.key
                }
            } else {
                s += `[${frame.index}]`
            }
        }
        return s;
    } catch (ex) {
        return '';
    }
}

function isEven(n) {
    return n % 2 === 0;
}

function readString(text, pos) {
    let i = pos + 1
    i = findEndQuote(text, i)
    var textpos = {
        text: text.substring(pos + 1, i),
        pos: i + 1
    }
    return textpos
}

// Find the next end quote
function findEndQuote(text, i) {
    while (i < text.length) {
        // console.log('findEndQuote: ' + i + ' : ' + text[i])
        if (text[i] === '"') {
            var bt = i
            // Handle backtracking to find if this quote is escaped (or, if the escape is escaping a slash)
            while (0 <= bt && text[bt] == '\\') {
                bt--
            }
            if (isEven(i - bt)) {
                break;
            }
        }
        i++
    }
    return i
}

四、新增组件monacoEditor.vue

<template>
  <div>
    <div id="code-editor" style="width:100%;height:100%;border:1px solid grey"></div>
  </div>
</template>

<script>
import * as monaco from 'monaco-editor'
import { getJsonPath } from '@/api/common/jsonpath/jsonpath'

export default {
  name: 'monacoEditor',
  model: {
    prop: 'content',
    event: 'change'
  },
  props: {
    'content': null,
    'language': {
      default: 'javascript'
    },
    'readOnly': {
      default: false
    }
  },
  data: function () {
    return {
      editor: null,
      jsonPath: null
    }
  },
  watch: {
    content: function (newValue) {
      console.debug("Code editor: content change");
      if (this.editor) {
        if (newValue !== this.editor.getValue()) {
          monaco.editor.setModelLanguage(this.editor.getModel(), this.language);
          this.editor.setValue(newValue);
          this.editor.trigger(this.editor.getValue(), 'editor.action.formatDocument')
        }
      }

    }
  },
  mounted: function () {
    const copyToClipboard = this.copyToClipboard
    this.editor = monaco.editor.create(
      this.$el.querySelector('#code-editor'),
      {
        value: this.content,
        language: this.language,
        theme: 'vs',
        readOnly: this.readOnly,
        automaticLayout: true
      }
    );
    this.editor.addAction({
      id: 'json-path',
      label: 'Copy JsonPath',
      keybindings: [
        monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_J)
      ],
      precondition: "editorLangId == 'json'",
      keybindingContext: "editorLangId == 'json'",
      contextMenuGroupId: '9_cutcopypaste',
      contextMenuOrder: 2,
      run: copyToClipboard
    });
    this.editor.onDidChangeModelContent(event => {
      const value = this.editor.getValue()
      if (this.value !== value) {
        this.$emit('change', value, event)
      }
    })
    this.editor.onDidChangeCursorPosition(event => {
      const value = this.editor.getValue()
      const offSet = this.editor.getModel().getOffsetAt(event.position)
      const language = this.language;
      if (this.value !== value && language === 'json') {
        this.$emit('on-cursor-change', { offSet: offSet })
      }
      if (language == 'json' && offSet !== 0) {
        this.jsonPath = getJsonPath(value, offSet)
        this.$emit('on-jsonpath-change', { jsonPath: this.jsonPath })
      }
    })
  },
  methods: {
    copyToClipboard () {
      const notification = this.$Notice
      if (this.jsonPath) {
        navigator.clipboard.writeText(this.jsonPath)
          .then(function () { }, function () {
            notification.error({
              title: 'jsonpath copy failed.'
            });
          }
          );
      } else {
        notification.warning({
          title: 'There is no jsonpath that can be copied.'
        });
      }
    }
  }
};
</script>

五、调用组件

import MonacoEditor from '@/components/MonacoEditor';

components: {
	MonacoEditor,
}

<monaco-editor 
            v-model="content"
            language="json"
            :readOnly="false" >
	        </monaco-editor>

六、参考地址

https://github.com/matt-oconnell/vue-monaco-editor
https://microsoft.github.io/monaco-editor/
https://github.com/Meituan-Dianping/lyrebird

Q.E.D.


Nothing really matters to me!