Vue3,使用monaco-editor实现sql语法高亮,自动/手动格式化

一:安装monaco-editor

npm install monaco-editor

二:使用

import * as monaco from "monaco-editor";
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";

三:封装基本组件

<template>
  <div class="codemirror">
    <div id="monacoEditor" ref="editorRef" class="monaco-editor"></div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import * as monaco from "monaco-editor";
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";

// 定义从父组件接收的属性
const props = defineProps({
  options: {
    type: Object,
    default: () => ({
      theme: "dark",
    }),
  },
  sqlCode: {
    type: String,
  },
});

const emits = defineEmits(["newSqlCode"]);

//解决 Monaco Editor 无法正确加载其所需的 Web Worker
self.MonacoEnvironment = {
  getWorker(workerId, label) {
    return new editorWorker();
  },
};

//初始化
const init = () => {
  editor = monaco.editor.create(document.getElementById("monacoEditor"), {
    value: props.sqlCode, //值
    wordBasedSuggestions: true, // 基于单词的自动完成
    autoIndex: true, // 控制是否开启自动索引。当开启时,编辑器会自动创建索引以加速搜索和语义高亮。
    fontSize: 14, // 字体大小
    language: "sql", //语言
    theme: props.options.theme, //主题
    readOnly: false, // 是否只读
    overviewRulerBorder: false, // 滚动是否有边框
    cursorSmoothCaretAnimation: true, // 控制光标平滑动画的开启与关闭。当开启时,光标移动会有平滑的动画效果。
    formatOnPaste: true, //设置是否在粘贴文本时自动格式化代码
    mouseWheelZoom: true, //设置是否开启鼠标滚轮缩放功能
    folding: true, //控制是否开启代码折叠功能
    automaticLayout: true, // 控制编辑器是否自动调整布局以适应容器大小的变化
    minimap: {
      // 关闭代码缩略图
      enabled: false, // 是否启用预览图
    },
    scrollBeyondLastLine: false, // 禁用额外滚动区
    scrollbar: {
      verticalScrollbarSize: 2, // 垂直滚动条宽度,默认px
      horizontalScrollbarSize: 2, // 水平滚动条高度
    },
    glyphMargin: true, //字形边缘
    wordWrap: "on", // 开启自动换行
    ...props.options,
  });
  // 监听编辑器内容变化
  editor.onDidChangeModelContent(() => {
    const value = handleValue();
    // 更新父组件的值
    emits("newSqlCode", value);
  });
};

//获取编辑器的内容
const handleValue = () => {
  return editor.getValue();
};

// 组件挂载后创建编辑器实例
onMounted(() => {
  init();
});

onBeforeUnmount(() => {
  if (editor) {
    // 组件卸载前销毁编辑器实例
    editor.dispose();
  }
});

</script>

<style lang="less" scoped>
.monaco-editor {
  height: 300px;
  width: 100%;
}
</style>

注意:如果editor是用ref定义的,const editor = ref(null),在调用editor的方法的时候,需要使用toRaw(editor)。否则页面会卡死。

//获取编辑器的内容
const handleValue = () => {
  //vue3中直接使用getValue会导致页面卡死,需要使用toRaw(),拿到原始数据,对原始数据进行修改,不会被追踪,不会更新UI界面
  return toRaw(editor).getValue();
};

四:实现格式化功能

一:自动格式化
import { format } from "sql-formatter";

//在初始化函数里面
const init = () => {
  editor = monaco.editor.create(document.getElementById("monacoEditor"), {
    value: props.sqlCode, //值
    autoIndex: true, // 控制是否开启自动索引。当开启时,编辑器会自动创建索引以加速搜索和语义高亮。
    fontSize: 14, // 字体大小
    language: "sql", //语言
    theme: props.options.theme, //主题
    readOnly: false, // 是否只读
    glyphMargin: true, //字形边缘
    wordWrap: "on", // 开启自动换行
    ...props.options,
  });

  // 监听编辑器内容变化
  editor.onDidChangeModelContent(() => {
    const value = handleValue();
    // 更新父组件的值
    emits("newSqlCode", value);
  });

  /*
   * 自动格式化内容。由于放在初始化函数中去执行,有可能出现数据还没传递进来就调用了格式化代码,因此加了个定时器去延时调用。
  */
  setTimeout(() => {
    editor.setValue(format(editor.getValue()));
  }, 0);
}
二:实现右键手动格式化
import { format } from "sql-formatter";

//在初始化函数里面
const init = () => {
  editor = monaco.editor.create(document.getElementById("monacoEditor"), {
    value: props.sqlCode, //值
    autoIndex: true, // 控制是否开启自动索引。当开启时,编辑器会自动创建索引以加速搜索和语义高亮。
    fontSize: 14, // 字体大小
    language: "sql", //语言
    theme: props.options.theme, //主题
    readOnly: false, // 是否只读
    glyphMargin: true, //字形边缘
    wordWrap: "on", // 开启自动换行
    ...props.options,
  });

  // 监听编辑器内容变化
  editor.onDidChangeModelContent(() => {
    const value = handleValue();
    // 更新父组件的值
    emits("newSqlCode", value);
  });

  /**
   * 添加右键格式化菜单
   */
  // 用于控制切换该菜单键的显示
  const shouldShowSqlRunnerAction = editor.createContextKey(
    "shouldShowSqlRunnerAction",
    false
  );
  // 前面已经定义了 editor
  // 添加 action
  editor.addAction({
    // id
    id: "sql-format",
    // 该菜单键显示文本
    label: "Format SQL",
    // 控制该菜单键显示
    precondition: "shouldShowSqlRunnerAction",
    // 该菜单键位置
    contextMenuGroupId: "navigation",
    contextMenuOrder: 1.5,
    // 点击该菜单键后运行
    run: (event) => {
      // 格式化代码
      editor.setValue(format(editor.getValue()));
    },
  });
  // 显示
  shouldShowSqlRunnerAction.set(true);
}

格式化前

格式化后

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值