代码编辑器之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编辑器真的是很强大,基本上很多编辑器功能都可以实现了,各种语言支持,代码智能提示等。

相关推荐
Vicky&James6 分钟前
WPF到Web的无缝过渡:英雄联盟客户端项目OpenSilver迁移实战
前端·wpf
m0_748233649 分钟前
RabbitMQ 进阶
android·前端·后端
不想有bug的小菜鸟18 分钟前
vue3使用iframe全屏展示pdf效果
前端·pdf
m0_7482386318 分钟前
Spring Boot项目接收前端参数的11种方式
前端·spring boot·后端
u01005596019 分钟前
前端代理,解决跨域问题讲解
前端
quitv24 分钟前
react脚手架配置别名
前端·javascript·react.js
m0_5287238133 分钟前
前端如何进行性能优化
前端·性能优化
化作繁星35 分钟前
在 Vue 3 中,如何缓存和复用动态组件
前端·vue.js·缓存
一粒沙-1 小时前
iOS 将GIF图分享至微信
前端·ios
graywen1 小时前
从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
前端