代码编辑器之monaco-editor 实现可编辑的git diff效果

MonacoEditor编辑器

简介

底层vscode开发的一款编辑器,各方面的样式功能基本与vscode一致。

官方文档

Monaco Editor (microsoft.github.io)

安装

安装时两者版本要对应,对应版本在后面,有时候版本对不上,会存在一定的问题。

sql 复制代码
npm install monaco-editor@0.28.1 --save-dev
npm install monaco-editor-webpack-plugin@4.2.0 --save-dev

常用属性

以下是较为常见的属性,其它属性可参考官网。

js 复制代码
value: this.editorValue, // 编辑器初始显示文字
theme: 'CodeSampleTheme', // 官方自带三种主题vs, hc-black, or vs-dark
language: 'json', // 支持json、js等,更多语言支持自行查阅demo,
overviewRulerBorder: false, // 滚动是否有边框
automaticLayout: true, // 自动布局
readOnly: false, // 是否只读
minimap: { // 关闭代码缩略图
  enabled: false // 是否启用预览图
},
lineNumbers: 'off', // 控制行号的显隐
scrollBeyondLastLine: false, // 禁用额外滚动区
scrollbar: {
  verticalScrollbarSize: 4, // 垂直滚动条宽度,默认px
  horizontalScrollbarSize: 4 // 水平滚动条高度
},
contextmenu: false // 禁用右键菜单

示例demo

第一步,配置monaco-editor-webpack-plugin

在项目中webpack的配置文件中,引入该plugin。

js 复制代码
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');

module.exports = {
	...
	plugins: [new MonacoWebpackPlugin()]
};

第二步,封装vue组件

可以将组件命名为monaco-diff

vue 复制代码
<template>
    <div class="monaco-container">
      <div ref="container" class="monaco-editor" :style="{height:height,width:width}"></div>
    </div>
</template>
  
<script>
  import * as monaco from 'monaco-editor';
  export default {
    name: 'MonacoEditor',
    props: {
      prevCodes:{
        type: String,
        default: ''
      },
      currentCodes:{
        type: String,
        default: ''
      },
      width: {
        type: String,
        default: '400px'
      },
      height: {
        type: String,
        default: '500px'
      },
      readOnly: {
        type: Boolean,
        default: false
      },
      editorOptions:{
        type: Object,
        default: () => {
          return {
            originalEditable:true,
            selectOnLineNumbers: true,
            roundedSelection: false,
            readOnly: false,
            cursorStyle: 'line',
            automaticLayout: true,
            glyphMargin:true,// 字形边缘
            useTabStops:false,
            scrollBeyondLastLine: false,
            wordWrap: 'on',
            wordWrapColumn: 80,
            wrappingIndent: 'indent',
            autoIndent: true,
            formatOnPaste: true // 复制粘贴时格式化
        }
      },
      theme:{
        type: String,
        default: 'vs-dark'
      }
    },
    watch:{
      prevCodes(val){
        if(this.monacoEditor){
          const originModel=monaco.editor.createModel(val,'json');
          const modifyModel=monaco.editor.createModel(this.currentCodes,'json');
          this.monacoEditor.setModel({
            originModel:originModel,
            modifyModel:modifyModel
          })
        }
      },
      currentCodes(val){
        if(this.monacoEditor){
          const originModel=monaco.editor.createModel(this.prevCodes,'json');
          const modifyModel=monaco.editor.createModel(val,'json');
          this.monacoEditor.setModel({
            originModel:originModel,
            modifyModel:modifyModel
          })
        }
      }
    },
    mounted() {
      this.monacoEditor=monaco.editor.createDiffEditor(this.$refs.container,{
        language:'json',
        theme:this.theme,
        automaticLayout:true,
        diffCodeLens: true,
        readOnly:this.readOnly,
        ...this.editorOptions
      })
      const originModel=monaco.editor.createModel(this.prevCodes,'json');
      const modifyModel=monaco.editor.createModel(this.currentCodes,'json');
      this.monacoEditor.setModel({
        originModel:originModel,
        modifyModel:modifyModel
      })
    },
    beforeDestroy() {
      if(this.monacoEditor){
        this.monacoEditor.dispose();
      }
    },
}
}
</script>
  
<style lang="less" scoped>
  .monaco-container{
    border: 1px solid #ddd;
  }
</style>

第三步,引入组件

在业务组件中,引入上一步封装的组件,使用即可。

vue 复制代码
<template>
    <monaco-diff :preCodes="prevCodes" :currentCodes="currentCodes" ref="diffResultRef" />
</template>
  
<script>
  import monacoDiff from './monaco-diff'
  export default {
    components:{
      monacoDiff
    },
    data(){
      return {
        prevCodes:'',
        currentCodes:''
      }
    },
    mounted() {
      // 赋值的话正常把值赋值给prevCodes和currentCodes即可,比如下面这样
      this.prevCodes='{"name":"test","age":18,"sex":"男","address":"北京"}'
      this.currentCodes='{"name":"test","age":18,"sex":"男","address":"北京","phone":"13123123123"}'
    },
    methods: {
      // 获取编辑器两边的值
      getValue(){
        const {modified,original}=this.$refs.diffResultRef.monacoEditor.getModel();
        return {
          modified:modified.getValue(),
          original:original.getValue()
        }
      }
    },
}
</script>
  
<style>
  
</style>

就能看到两边内容类似git diff的效果了

不得不说monaco编辑器真的是很强大,基本上很多编辑器功能都可以实现了,各种语言支持,代码智能提示等。

相关推荐
啾咪orJIUMI7 小时前
Vue 3 + 高德地图封装实战:点位、区域、Loca 流光与 Vue 信息窗体
前端·vue.js
掘金者阿豪7 小时前
AI数据库不只是向量检索:从数据语义到库内智能计算的技术演进
前端
梦里寻码7 小时前
我用 NestJS + Vue3 写了一套完整的研发管理系统(58 表 / 229 API / 130 项断言,全开源
前端·后端·算法
FRing037 小时前
vue2干货总结8(路由模块封装、router-link、声明式导航、路由重定向、编程式导航)
开发语言·前端·vue.js·vue2
SameX7 小时前
HarmonyOS ArkUI Dialog 复用 用 @CustomDialog + enum type 做多类型统一管理的做法
前端
AiMan7 小时前
豆包爱学还是不可以导出左侧所有对话,只能单容导出,方法不对吗
前端
无懈可击7 小时前
Vue 可视化AI表单设计器 FcDesigner v3.6 版本发布,支持导出 SQL功能!
vue.js·开源·ai编程
AiMan8 小时前
Grok生成的内容能否下载吗?
前端
徐小夕8 小时前
JitArchives,一款基于JitWord协同AI文档打造的企业级电子档案系统
前端·vue.js·github
陈随易8 小时前
Node.js 2026上半年都有哪些性能提升?
前端·后端·程序员