Johu

Vue 中使用 Monaco Editor

最近的使命就是,在找好用的代码编辑器🤪
尝试了codeMirror 感觉咋用咋不顺手,简单的代码编辑还能应付,复杂一点的配置就搞得头昏眼花🙄,而且和 vue 一起用简直命里犯冲🤬
机缘巧合就找到了救世主 Monaco Editor

安装配置

npm官网

  1. npm i monaco-editor
  2. npm install monaco-editor-webpack-plugin --save-dev
  3. vue.config.js文件配置
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
module.exports = {
  chainWebpack: (config) => {
    config.plugin('monaco').use(new MonacoWebpackPlugin())
  }
}

代码编辑

用到了"element-ui": "^2.15.6"

<template>
  <div class="myEditor">
          <el-form :inline="true" ref="form">
              <el-form-item>
                  <el-select v-model="theme" size="mini" @change="themeChange" placeholder="主题">
                      <el-option
                              v-for="item in themeOption"
                              :key="item.value"
                              :label="item.label"
                              :value="item.value">
                      </el-option>
                  </el-select>
              </el-form-item>
              <el-form-item>
                  <el-select v-model="language" size="mini" filterable @change="languageChange" placeholder="语言">
                      <el-option
                              v-for="item in languageOption"
                              :key="item.id"
                              :label="item.id"
                              :value="item.id">
                      </el-option>
                  </el-select>
              </el-form-item>
          </el-form>
      <div id="container" ref="container"></div>
  </div>
</template>
<script>
import * as monaco from 'monaco-editor'
export default {
  data () {
    return {
      themeOption: [
        {
          value: 'vs',
          label: '默认'
        },
        {
          value: 'hc-black',
          label: '高亮'
        },
        {
          value: 'vs-dark',
          label: '深色'
        }
      ],
      languageOption: [],
      theme: 'vs',
      language: 'plaintext'
    }
  },
  mounted () {
    const self = this
    self.initEditor()
    self.languageOption = monaco.languages.getLanguages()
  },
  methods: {
    initEditor () {
      const self = this
      const domEditor = document.getElementById('container')
      self.monacoEditor = monaco.editor.create(domEditor, {
        theme: self.theme,
        readOnly: false,
        automaticLayout: true
      })
    },
    themeChange (val) {
      monaco.editor.setTheme(val)
    },
    languageChange (val) {
      monaco.editor.setModelLanguage(this.monacoEditor.getModel(), val)
    }
  }
}
</script>
<style scoped>
  #container{
      width: 100vw;
      height: calc(100vh - 41px);
    text-align: left;
  }
  .el-form-item{
      margin-bottom: 0;
      margin-left: 10px;
  }
</style>

代码对比

用到了"element-ui": "^2.15.6"

<template>
  <div class="myEditor">
          <el-form :inline="true" ref="form">
              <el-form-item>
                  <el-select v-model="theme" size="mini" @change="themeChange" placeholder="主题">
                      <el-option
                              v-for="item in themeOption"
                              :key="item.value"
                              :label="item.label"
                              :value="item.value">
                      </el-option>
                  </el-select>
              </el-form-item>
              <el-form-item>
                  <el-select v-model="language" size="mini" filterable @change="languageChange" placeholder="比对语言">
                      <el-option
                              v-for="item in languageOption"
                              :key="item.id"
                              :label="item.id"
                              :value="item.id">
                      </el-option>
                  </el-select>
              </el-form-item>
              <el-form-item style="float: right">
                  {{diffNum}}处差异
              </el-form-item>
          </el-form>
      <div id="container" ref="container"></div>
  </div>
</template>
<script>
import * as monaco from 'monaco-editor'
export default {
  data () {
    return {
      themeOption: [
        {
          value: 'vs',
          label: '默认'
        },
        {
          value: 'hc-black',
          label: '高亮'
        },
        {
          value: 'vs-dark',
          label: '深色'
        }
      ],
      languageOption: [],
      theme: 'vs',
      language: 'plaintext',
      diffNum: 0
    }
  },
  mounted () {
    const self = this
    self.initEditor()
    self.setModel('', '')
    self.languageOption = monaco.languages.getLanguages()
  },
  methods: {
    initEditor () {
      const self = this
      const domEditor = document.getElementById('container')
      self.monacoEditor = monaco.editor.createDiffEditor(domEditor, {
        theme: self.theme,
        readOnly: false,
        domReadOnly: false,
        originalEditable: true,
        automaticLayout: true
      })
      self.monacoEditor.onDidUpdateDiff(()=>{
        self.diffNum = this.monacoEditor.getLineChanges().length
      })
    },
    themeChange (val) {
      monaco.editor.setTheme(val)
    },
    languageChange (val) {
      console.log(val);
      monaco.editor.setModelLanguage(this.monacoEditor.getModel().original, val)
      monaco.editor.setModelLanguage(this.monacoEditor.getModel().modified, val)
    },
    setModel (original, modified) {
      this.monacoEditor.setModel({
        original: monaco.editor.createModel(original, this.language),
        modified: monaco.editor.createModel(modified, this.language)
      })
    }
  }
}
</script>
<style scoped>
  #container{
      width: 100vw;
      height: calc(100vh - 41px);
    text-align: left;
  }
  .el-form-item{
      margin-bottom: 0;
      margin-left: 10px;
  }
</style>

代码对比增加下一处差异功能

monaco提供的方法会直接跳转到指定的差异位置。

// 创建差异指南
self.diffNavigator = monaco.editor.createDiffNavigator(this.monacoEditor,{
        alwaysRevealFirst:true
      })
// 上一处差异
self.diffNavigator.previous()
// 下一处差异
self.diffNavigator.next()

右键面板增加操作

self.monacoEditor.addAction({
        id: 'nextDiff', // 菜单项 id
        label: '上一处差异', // 菜单项名称
        keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.PageUp], // 绑定快捷键,是 monacoEditor 自定义的对应关系
        contextMenuGroupId: 'navigation', // 所属菜单的分组
        run: () => self.nextDiff(), // 点击后执行的操作
      })
self.monacoEditor.addAction({
        id: 'nextDiff', // 菜单项 id
        label: '下一处差异', // 菜单项名称
        keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.PageDown], // 绑定快捷键
        contextMenuGroupId: 'navigation', // 所属菜单的分组
        run: () => self.nextDiff(), // 点击后执行的操作
      })

部分配置解释

配置名称 功能
automaticLayout 自适应布局
readOnly 只读
theme 主题
originalEditable 源比较代码可编辑(代码对比)

才艺展示

代码编辑

代码对比

参考

官网
时间脱臼

posted @ 2021-09-18 16:09  Johu  阅读(3695)  评论(0编辑  收藏  举报