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

相关推荐
Thanks_ks22 分钟前
从零手写一个 Promise:深入理解 JavaScript 异步编程的本质
javascript·promise·事件循环·异步编程·手写源码·前端进阶·promises/a+
胡萝卜术7 小时前
力扣5. 最长回文子串
前端·javascript·面试
我星期八休息8 小时前
网络编程—应用层HTTP协议
linux·运维·开发语言·前端·网络·网络协议·http
不好听6138 小时前
前端路由完全指南(下篇):懒加载、History 栈与工程化实践
前端·react.js
触底反弹10 小时前
🔥 从零搭建 RAG 知识库:爬虫→分词→向量化→检索,一步都不能错
javascript·人工智能·面试
圣光SG10 小时前
Java Web入门基础知识笔记
java·前端·笔记
cyforkk11 小时前
Vercel 绑定自定义域名极简配置指南
服务器·前端·网络
এ慕ོ冬℘゜12 小时前
JavaScript 数组核心方法实战|新增元素 + 数组转字符串 零基础详解
开发语言·javascript·ecmascript
IT_陈寒12 小时前
React useEffect依赖数组中埋的坑,这次终于让我逮到了
前端·人工智能·后端