vue中monaco-editor的封装与使用

2,441 阅读1分钟

1685439717600.jpg

在对比了很多的代码编辑器之后,最终还是选择了monaco-editor作为首选,功能强大,扩展性也很好,可以很好的根据设计图完成所需要的效果,也提供了很多的属性及事件供使用

先看下实现的效果,这是一个页面引用了多个monaco-editor组件的效果

image.png

第一步:安装monaco-editor

// webpack5可以选择较新的版本
npm install --save monaco-editor@0.30.1
    
// 和monaco-editor版本对应,vue2可以按照当前版本进行安装
npm install --save monaco-editor-webpack-plugin@6

已踩过坑,按照当前版本安装,不会出错

第二步:在vue.config.js中配置webpack插件


const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
module.exports = {
    ...
    plugins: [
        ...
        new MonacoWebpackPlugin() // 这里使用
    ],
}

第三步:封装组件

在components中新建monacoEditor文件夹,增加index.vue文件。

代码:

    <template>
      <div style='width:100%;height:100%;'>
        <div :id="editorId" style='width:100%;height:100%;'></div> <!--宽高自行设定 -->
      </div>
    </template>

注意当前id为动态id,使用动态id的原因,主要是因为可能一个页面会多次使用,如果id相同,会导致后期的传值只会传递给最后一个引入monaco的组件

<script>
import * as monaco from 'monaco-editor' // 引入monaco框架
export default {
  name: 'MonacoEditor',
  data () {
    return {
      monacoEditor: null
    }
  },
  props: { // 接收页面传值
    readOnly: {
      type: Boolean,
      default: false
    },
    height: {
      type: String,
      default: '100px'
    },
    width: {
      type: String,
      default: '100%'
    },
    editorId: {
      type: String,
      default: ''
    }
  },
  watch: {
    height () {
      this.reSize()
    },
    width () {
      this.reSize()
    },
    editorId: {
      handler (val) {
        if (val) {
          this.editorMounted(val)
        }
      },
      deep: true,
      immediate: true
    }
  },
  mounted () {
  },
  methods: {
    editorMounted (val) { // 创建一个代码编辑器实例
      this.$nextTick(() => {
        const data = {}
        const model = monaco.editor.createModel(JSON.stringify(data), 'json') // 创建一个新的文本模型实例
        const params = {
          language: 'javascript', // 当前使用的编辑器的语言,可以根据个人需求设置所需语言,也可以通过父组件中传入的方式使用(目前使用的是javascript)
          automaticLayout: true, // 是否可以允许自动调整布局以适应父容器的大小,当启用时,编辑器会根据所在容器大小发生变化,如果禁用了,则会保持初始大小,不会根据父元素进行自动调整
          readOnly: this.readOnly, // 控制编辑器是否只读,不允许进行编辑
          theme: 'vs-dark', // 编辑器的主题,可选项有:vs,vs-drak,hc-block,hc-light
          model: model, // 设置编辑器的初始值
          minimap: {
            enabled: false
          },
          fontSize: 14 // 编辑器的字体大小
        }
        this.monacoEditor = monaco.editor.create(document.getElementById(val), params) // 根据id创建一个编辑器实例
      })
    },
    setVal (value) { // 给编辑器中传入值
      this.monacoEditor.setValue(value)
    },
    setTri () { // 格式化编辑器中的字符串
      if (this.readOnly) { // 注意:当编辑器是只读状态的话,无法对编辑器中的内容进行格式化操作
        this.monacoEditor.updateOptions({ readOnly: false })
        this.monacoEditor.trigger('提示', 'editor.action.formatDocument')
        setTimeout(() => {
          this.monacoEditor.updateOptions({ readOnly: true })
        }, 200)
      } else {
        this.monacoEditor.trigger('提示', 'editor.action.formatDocument')
      }
    },
    getVal () { // 获取组件中录入的值
      return this.monacoEditor.getValue()
    },
    reSize () { // 当宽高改变时重新布局编辑器
      this.$nextTick(() => {
        this.monacoEditor.layout()
      })
    }
  },
  beforeDestroy () { // 释放编辑器占用的资源
    this.monacoEditor.dispose()
  }
}
</script>

第四步:页面中引用组件

<template>
    <div class='interApiRequest'>
        <div class='table' style='margin-top:10px;height:500px' v-if='getBodyRadio==="json"'>
            <monace-editor :readOnly="false" ref='monaceEditorJSON' :editorId='"monaceEditorJSON"'>
            </monace-editor>
        </div>
    </div>
</html>

注意:父容器需要指定高度,否则编辑器的高度不会随着父容器的高度改变,会影响界面效果

import monaceEditor from '@/components/monacoEditor/index.vue',
export default {
    name: 'IntegratComAuthApiRequest',
    components: {
        monaceEditor
    }
}

获取代码编辑器组件中的值

this.$refs.monaceEditorJSON.getVal() // 注意获取到的是字符串

设置代码编辑器组件中值及进行格式化

this.$refs.monaceEditorJSON.setVal(val)
this.$refs.monaceEditorJSON.setTri()