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

MonacoEditor编辑器

简介

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

官方文档

Monaco Editor (microsoft.github.io)

安装

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

sql 复制代码
npm install [email protected] --save-dev
npm install [email protected] --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编辑器真的是很强大,基本上很多编辑器功能都可以实现了,各种语言支持,代码智能提示等。

相关推荐
珹洺37 分钟前
JSP技术入门指南【一】利用IDEA从零开始搭建你的第一个JSP系统
java·开发语言·前端·html·intellij-idea·jsp
2401_878454534 小时前
Themeleaf复用功能
前端·学习
葡萄城技术团队5 小时前
基于前端技术的QR码API开发实战:从原理到部署
前端
八了个戒7 小时前
「数据可视化 D3系列」入门第三章:深入理解 Update-Enter-Exit 模式
开发语言·前端·javascript·数据可视化
noravinsc7 小时前
html页面打开后中文乱码
前端·html
胚芽鞘6818 小时前
vue + element-plus自定义表单验证(修改密码业务)
javascript·vue.js·elementui
小满zs8 小时前
React-router v7 第四章(路由传参)
前端·react.js
小陈同学呦8 小时前
聊聊双列瀑布流
前端·javascript·面试
键指江湖8 小时前
React 在组件间共享状态
前端·javascript·react.js