Bootstrap

MonacoEditor 自动格式化sql json数据

先上个效果吧:
在这里插入图片描述

安装:
npm install vue-monaco-editor
script中引用:
import MonacoEditor from ‘vue-monaco-editor’

  • 引用MonacoEditor组件时,如果不需要格式化,可以给组件设置:code=“code”,在请求数据后将后台返回的值赋给:code绑定的变量就行了。如果需要格式化,也可以将v-bind:code去掉,setValue会给其赋值的

<template>
  <el-dialog
    width="100%"
    :title="title"
    :visible.sync="visible"
    :fullscreen="true"
    append-to-body
    :before-close="handleClosed"
    custom-class="debug-dialog"
  >
    <div class="info-title">sql:</div>
      <div style="height: 200px; border: 1px solid #ddd">
        <MonacoEditor
          :code="sqlCode"
          :key="randomkey1"
          :editorOptions="options"
          theme="vs"
          @mounted="onMounted"
          @codeChange="onCodeChange"
        >
        </MonacoEditor>
      </div>
      <div class="info-title">json:</div>
      <div style="height: 200px; border: 1px solid #ddd">
        <MonacoEditor
          language="json"
          :key="randomkey2"
          :editorOptions="options"
          theme="vs"
          @mounted="onMounted2"
        >
        </MonacoEditor>
      </div>
    <span slot="footer" class="dialog-footer">
      <el-button type="primary" @click="confirm">确定</el-button>
    </span>
  </el-dialog>
</template>

定义变量

data () {
    return {
      editor1: null, // 用来展示SQL的编辑器
      editor2: null, // 用来展示JSON的编辑器
      options: {
        selectOnLineNumbers: false,
        // language: 'json',
        automaticLayout: true,
        tabSize: 2,
        overviewRulerBorder: false,
        scrollBeyondLastLine: false,
        minimap: {
          enabled: false // 不要小地图
        },
        fontSize: "14px",
        autoIndent:true,//自动布局
      },
      // 用于刷新组件
      randomkey1:'',
      randomkey2:'',
      // 初始化时编辑器展示的数据
      sqlCode: '',
      // jsonCode: '' // json的就不给它初始化数据了,只读也不需要获取录入的内容,等获取到数据时给编辑器setValue
    }
  },

设置是否只读状态

onMounted1(editor) {
    // sql部分
    this.editor1 = editor;
    this.editor1.updateOptions({
      readOnly: false
    });
  },

获取编辑时的字符内容

onCodeChange(editor) {
   this.sqlCode = this.editor.getValue();
 },

美化sql

安装sql-formatter
npm install --save sql-formatter

★如果安装后有报错,可以降低版本。我当时报错,切换成了npm install --save [email protected]
import { format } from ‘sql-formatter’

// 美化sql
this.editor1.setValue(format(sqlCode,{ language: 'sql' }))

格式化json

this.editor2.setValue(jsonCode)
 /*
    触发自动格式化;
    'editor.action.format'这个是固定的值,插件方法中的一个字段名,
    有的文章是叫'editor.action.formatDocument',具体可以自己在控制台打印,链接到函数中去看
   */
  this.editor2.trigger('','editor.action.format') 
  // 强制刷新一次
  this.editor2.setValue(this.editor2.getValue()) 

★★★注意:
这里我的json编辑器是需要只读的,如果在onMounted中直接设置它的readOnly: true,是格式化不了的。需要先设置为false,然后获取到后台数据时,格式化处理后再将readOnly设置成true。

写在最后★★★

this.editor2.setValue()
使用这个方法设置值时,要确保this.editor2.赋值成功才行。父组件异步请求数据的方法,与子组件onMounted2()方法的加载顺序一定要考虑进去。

如果页面只有一个编辑器展示的话,可以在onMounted2方法中,给this.editor2赋完值后请求数据接口。

我这里是多个编辑器展示,而且所有数据都在一个接口中,所以就用了setTimeOut延时 去等到所有编辑器赋值完后去处理需要格式的数据,如果有更好的解决方法,请在评论区指教一下

JS完整代码



<script>
import MonacoEditor from 'vue-monaco-editor'
// ★如果安装后有报错,可以降低版本。我当时报错,切换成了npm install --save [email protected]
import { format } from 'sql-formatter'
export default {
  name: "debug-dialog",
  components: { MonacoEditor },
  props: {
    title: String,
    visible: Boolean,
    record: Object
  },
  data () {
    return {
      editor1: null,
      editor2: null,
      options: {
        selectOnLineNumbers: false,
        // language: 'json',
        automaticLayout: true,
        tabSize: 2,
        overviewRulerBorder: false,
        scrollBeyondLastLine: false,
        minimap: {
          enabled: false // 不要小地图
        },
        fontSize: "14px",
        autoIndent:true,//自动布局
      },
      randomkey1:'',
      randomkey2:''
    }
  },
  created() {
    this.getAllDataByRefId();
  },
  methods: {
    onMounted1(editor) {
      // sql部分
      this.editor1 = editor;
      this.editor1.updateOptions({
        readOnly: false
      });
    },
    onMounted2(editor) {
      // json部分
      this.editor2 = editor;
      // ★划重点:如果想要把json框框设置为只读,要先将此处设置为可编辑,然后拿到后台数据格式化后再设置为true
      this.editor2.updateOptions({
        readOnly: false
      });
    },
    // sql编辑
    onCodeChange(editor) {
      this.sqlCode = this.editor.getValue();
    },
    // 异步获取数据
    getAllDataByRefId() {
      let param = {
        uuid: this.record.refId
      }
      api.getAllDataByRefId(param, res=> {
        if (res.meta.success) {
          if (res.data) {
            let sqlCode = res.data.sqlCode,
	            jsonCode = res.data.jsonCode
            /*
              这里我用的延时来解决数据加载顺序问题,如果有更好的方式,欢迎赐教
              因为editor在onMounted渲染时 后台数据可能还未加载出来
              所以延时等this.editor1、editor2赋完值 再去操作数据
            */
            setTimeout(() => {
              // 将sql字符串进行格式后放入编辑器中
              this.editor1.setValue(format(sqlCode,{ language: 'sql' }))

              // 参数是编辑器需要展示的json字符串
              this.editor2.setValue(jsonCode)
              /*
                触发自动格式化;
                'editor.action.format'这个是固定的值,插件方法中的一个字段名,
                有的文章是叫'editor.action.formatDocument',具体可以自己在控制台打印,链接到函数中去看
               */
              this.editor2.trigger('','editor.action.format') 
              // 强制刷新一次
              this.editor2.setValue(this.editor2.getValue()) 
              // 格式化后 将json部分设置为只读
              this.editor2.updateOptions({
                readOnly: true
              });
            }, 1000);
            // 这一步刷新也很重要,避免数据没有被更新掉
            this.fresh()
          }
        }
      })
    },
    fresh() {
      this.randomkey1 = new Date().getTime();
      this.randomkey2 = new Date().getTime();
    },
  },
}
</script>
;