Skip to content

Jason-chen-coder/Monaco-EasyCodeEditor

Repository files navigation

easy-codeeditor

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

1.什么是Monaco

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

官方API文档

2.Monaco Editor安装及使用

2.1安装

npm install monaco-editor --save-dev

npm install monaco-editor-webpack-plugin --save-dev

2.2配置vue.config.js

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

2.3 开始使用

2.3.1.vue文件中导入monaco
import * as monaco from 'monaco-editor'
2.3.2.创建代码编辑区域
 <div ref="container" class="monaco-editor"></div>

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: {}
    }
  },
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. 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. 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>
2.3.3.3 效果:

在这里插入图片描述

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)
      })
    }

效果::

在这里插入图片描述

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

效果:

在这里插入图片描述

Project setup

npm install

Compiles and hot-reloads for development

npm run serve

Compiles and minifies for production

npm run build

Lints and fixes files

npm run lint

Customize configuration

See Configuration Reference.