加载中...

【Monaco】Monaco-Editor在Vue中使用(实现代码编辑与diff代码比较)

【Monaco】Monaco-Editor在Vue中使用(实现代码编辑与diff代码比较)

Monaco在线代码编辑器使用总结

1.什么是Monaco

Monaco编辑器是为VS代码提供支持的代码编辑器
  • 1

官方API文档

2.Monaco Editor安装及使用

2.1安装
npm install monaco-editor --save-dev

npm install monaco-editor-webpack-plugin --save-dev
  • 1
  • 2
  • 3
2.2配置vue.config.js
const MonacoWebpackPlugin = require(''monaco-editor-webpack-plugin'')
module.exports = {
    configureWebpack: {
        plugins: [
            new MonacoWebpackPlugin()
        ]
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
2.3 开始使用
2.3.1.vue文件中导入monaco
import * as monaco from ''monaco-editor''
  • 1
2.3.2.创建代码编辑区域
 <div ref="container" class="monaco-editor"></div>
  • 1
2.3.3.初始化container
2.3.3.1 准备monaco基础配置
  data () {
    return {
      // 主要配置
      defaultOpts: {
       // 编辑器的值
        value: '''',
         // 编辑器主题:vs, hc-black, or vs-dark,更多选择详见官网
        theme: ''vs-dark'',
        // 右侧不显示编辑器预览框
        roundedSelection: true, 
        // 自动缩进
        autoIndent: true ,
        // 是否只读
        readOnly: false, 
        // 语言类型java,c,php更多选择详见官网
        language: ''javascript'', 
      }
        // 编辑器对象
      monacoEditor: {}
    }
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
2.3.3.2 初始化monaco编辑器
methods: {
    init () {
      // 初始化container的内容,销毁之前生成的编辑器
      this.$refs.container.innerHTML = ''''
      // 生成编辑器配置
      let editorOptions = Object.assign(this.defaultOpts, this.opts)
      // 生成编辑器对象
      this.monacoEditor = monaco.editor.create(this.$refs.container, editorOptions)
      // 编辑器内容发生改变时触发
      this.monacoEditor.onDidChangeModelContent(() => {
        this.$emit(''change'', this.monacoEditor.getValue())
      })
    },
   // 手动编辑器中的内容
   getValue() {
        this.$message.info(this.$refs.monaco.getVal())
    },
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
整体源码:
  1. monacoeditor.vue
<template>
  <div
    ref="container"
    class="monaco-editor"
    :style="`height: ${height}px`"
  ></div>
</template>
<script>
import * as monaco from ''monaco-editor''
export default {
  name: ''AcMonaco'',
  props: {
    opts: {
      type: Object,
      default () {
        return {}
      }
    },
    height: {
      type: Number,
      default: 300
    }
  },
  data () {
    return {
      // 主要配置
      defaultOpts: {
        value: '''', // 编辑器的值
        theme: ''vs-dark'', // 编辑器主题:vs, hc-black, or vs-dark,更多选择详见官网
        roundedSelection: true, // 右侧不显示编辑器预览框
        autoIndent: true // 自动缩进
      },
      // 编辑器对象
      monacoEditor: {}
    }
  },
  watch: {
    opts: {
      handler () {
        this.init()
      },
      deep: true
    }
  },
  mounted () {
    this.init()
  },
  methods: {
    init () {
      // 初始化container的内容,销毁之前生成的编辑器
      this.$refs.container.innerHTML = ''''
      // 生成编辑器配置
      let editorOptions = Object.assign(this.defaultOpts, this.opts)
      // 生成编辑器对象
      this.monacoEditor = monaco.editor.create(this.$refs.container, editorOptions)
      // 编辑器内容发生改变时触发
      this.monacoEditor.onDidChangeModelContent(() => {
        this.$emit(''change'', this.monacoEditor.getValue())
      })
    },
    // 供父组件调用手动获取值
    getVal () {
      return this.monacoEditor.getValue()
    }
  }
}
</script>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  1. App.vue

<template>
  <div>
    <div id="app">
      <img
        alt="Vue logo"
        style="width: 200px; height: 200px"
        src="./assets/logo.png"
      />
      <h1>Easy-CodeEditor</h1>
      <div>
        语言:
        <el-select
          v-model="opts.language"
          clearable
          placeholder="请选择"
          size="mini"
          @change="changeLanguage"
        >
          <el-option
            v-for="item in sets.language"
            :key="item"
            :label="item"
            :value="item"
          >
          </el-option>
        </el-select>
        样式风格:
        <el-select
          v-model="opts.theme"
          clearable
          placeholder="请选择"
          size="mini"
          @change="changeTheme"
        >
          <el-option
            v-for="item in sets.theme"
            :key="item"
            :label="item"
            :value="item"
          >
          </el-option>
        </el-select>
        <el-button type="primary" size="mini" @click="getValue"
          >获取内容</el-button
        >
      </div>
    </div>
    <div>
      <!--调用子组件-->
      <monaco
        ref="monaco"
        :opts="opts"
        @change="changeValue"
        :height="600"
      ></monaco>
    </div>
  </div>
</template>
<script>
import monaco from ''./components/monacoeditor''
export default {
  components: { monaco },
  data () {
    return {
      sets: {
        language: {
          ''apex'': ''apex'',
          ''azcli'': ''azcli'',
          ''bat'': ''bat'',
          ''c'': ''c'',
          ''clojure'': ''clojure'',
          ''coffeescript'': ''coffeescript'',
          ''cpp'': ''cpp'',
          ''csharp'': ''csharp'',
          ''csp'': ''csp'',
          ''css'': ''css'',
          ''dockerfile'': ''dockerfile'',
          ''fsharp'': ''fsharp'',
          ''go'': ''go'',
          ''graphql'': ''graphql'',
          ''handlebars'': ''handlebars'',
          ''html'': ''html'',
          ''ini'': ''ini'',
          ''java'': ''java'',
          ''javascript'': ''javascript'',
          ''json'': ''json'',
          ''kotlin'': ''kotlin'',
          ''less'': ''less'',
          ''lua'': ''lua'',
          ''markdown'': ''markdown'',
          ''msdax'': ''msdax'',
          ''mysql'': ''mysql'',
          ''objective-c'': ''objective-c'',
          ''pascal'': ''pascal'',
          ''perl'': ''perl'',
          ''pgsql'': ''pgsql'',
          ''php'': ''php'',
          ''plaintext'': ''plaintext'',
          ''postiats'': ''postiats'',
          ''powerquery'': ''powerquery'',
          ''powershell'': ''powershell'',
          ''pug'': ''pug'',
          ''python'': ''python'',
          ''r'': ''r'',
          ''razor'': ''razor'',
          ''redis'': ''redis'',
          ''redshift'': ''redshift'',
          ''ruby'': ''ruby'',
          ''rust'': ''rust'',
          ''sb'': ''sb'',
          ''scheme'': ''scheme'',
          ''scss'': ''scss'',
          ''shell'': ''shell'',
          ''sol'': ''sol'',
          ''sql'': ''sql'',
          ''st'': ''st'',
          ''swift'': ''swift'',
          ''tcl'': ''tcl'',
          ''typescript'': ''typescript'',
          ''vb'': ''vb'',
          ''xml'': ''xml'',
          ''yaml'': ''yaml''
        },
        theme: {
          ''vs'': ''vs'',
          ''vs-dark'': ''vs-dark'',
          ''hc-black'': ''hc-black''
        }
      },
      opts: {
        value: '''',
        readOnly: false, // 是否可编辑
        language: ''javascript'', // 语言类型
        theme: ''vs-dark'' // 编辑器主题
      }
    }
  },
  methods: {
    changeLanguage (val) {
      this.opts.language = val
    },
    changeTheme (val) {
      this.opts.theme = val
    },
    // 手动获取值
    getValue () {
      this.$message.info(''代码已输出至控制台'');
      console.log(''输出代码:'' + this.$refs.monaco.getVal())
    },
    // 内容改变自动获取值
    changeValue (val) {
      console.log(val)
    }
  }
}
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
2.3.3.3 效果:

New Image

2.3.3.4 注意:

1)当我们修改了defaultOpts的配置后我们需要重新初始化monaco编辑器;即重新执行this.init();

2.4 编辑器代码diff的实现
init () {
 // 初始化container的内容,销毁之前生成的编辑器
      this.$refs.container.innerHTML = ''''
      // 生成编辑器配置
      let editorOptions = Object.assign(this.defaultOpts, this.opts)
       editorOptions.readOnly = true;
       editorOptions.language = ''javascript''
      // 初始化编辑器实例
      this.monacoDiffInstance = monaco.editor.createDiffEditor(this.$refs[''container''],editorOptions)
      this.monacoDiffInstance.setModel({
      // oldValue为以前的值
      original: monaco.editor.createModel(this.oldValue, editorOptions.language),
       // oldValue为新的值
      modified: monaco.editor.createModel(this.newValue, editorOptions.language)
      })
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

效果::
New Image

2.4.1切换为行内比较
//直接升级配置项 renderSideBySide: false 即可
this.monacoDiffInstance.updateOptions({
       renderSideBySide: false
     });
  • 1
  • 2
  • 3
  • 4

效果:
New Image

本文章项目地址