首页 前端知识 vue使用diff-match-patch和codemirror实现文本对比,实现合并功能

vue使用diff-match-patch和codemirror实现文本对比,实现合并功能

2024-05-12 17:05:35 前端知识 前端哥 191 303 我要收藏

前言

1.最近公司要求做一个可以类似于git代码比对的页面,然后支持右侧往左侧合并,实现回退版本的功能,使用了codemirror编辑器与diff-match-patch这个插件很好的实现了这个效果,代码可直接复用

实现效果

1.运行命令下载

//运行命令 下载依赖
npm install diff-match-patch -S
npm install codemirror

2.在项目中使用

不多说了,代码中皆有注释,且代码可直接复用,只要求说一点就是,获取最后左侧编辑器内的代码从他的实例里面是拿不到的,且初始化下方的方法,是为了获取当前有多少个差异地方的数量,放在右上角进行展示的,每次点击箭头都会保留剩余的差异数量,获取左侧修改后的编辑器内容,需要调用方法且可获得编辑器内容  ↓↓↓↓↓↓↓↓

   const newStr = this.HisCode.edit.getValue();

CSS类中我改动了他的样式,也是借鉴其他大佬的 

<template>
  <div class="compareClass">
    <div ref="CodeMirror"></div>
  </div>
</template>

<script>
import CodeMirror from 'codemirror';
import 'codemirror/lib/codemirror.css';
import 'codemirror/addon/merge/merge.js';
import 'codemirror/addon/merge/merge.css';
import DiffMatchPatch from 'diff-match-patch';
import {
  CstMixin,
} from 'boot/mixins/cst';

window.diff_match_patch = DiffMatchPatch;
window.DIFF_DELETE = -1;
window.DIFF_INSERT = 1;
window.DIFF_EQUAL = 0;

export default {
  name: 'CodeMirror',
  mixins: [CstMixin],
  props: {
    codeId: {
      type: String,
      defualt: '',
    },
    currentData: {
      type: Object,
      defualt: {},
    },
  },
  data() {
    return {
      historyCode: '',
      currentCode: '',
      HisCode: null,
      divide: '',
    };
  },
  created() {
  },
  mounted() {
    this.showLoading();
    if (this.currentData) {
      this.currentCode = `${this.currentData.template.value}\n//This is used to separate the code\n${this.currentData.js.value}\n//This is used to separate the code${this.currentData.css.value}`;
    }
    this.$nextTick(() => {
      this.getTemplateCode();
    });
  },
  methods: {
    getTemplateCode() {
      this.$axios.get(`xxxxxxxxxxxxid=${this.codeId}`).then((r) => {
        if (r.code === 200 && r.result) {
          this.hideLoading();
          const obj = r.result;
          this.historyCode = `${JSON.parse(obj.html).value}\n//This is used to separate the code\n${JSON.parse(obj.js).value}\n//This is used to separate the code${JSON.parse(obj.css).value}`;
          setTimeout(() => {
            this.initUI();
          }, 500);
        }
      }).finally(() => {
        this.hideLoading();
      });
    },
    backCurrCode() {
      const newStr = this.HisCode.edit.getValue();
      const [template, js, cssValue] = newStr.split('//This is used to separate the code');
      const codeData = {
        formMixin: false,
        template: {
          value: template.trim(), key: 'template', mode: 'text/x-vue', tab: '模板',
        },
        js: {
          value: js.trim(), key: 'js', mode: 'text/javascript', tab: '代码',
        },
        css: {
          value: cssValue.trim(), key: 'css', mode: 'text/css', tab: '样式',
        },
      };
      this.$emit('getNewData', codeData);
    },
    // 初始化
    initUI() {
      const target = this.$refs.CodeMirror;
      target.innerHTML = '';
      this.HisCode = CodeMirror.MergeView(target, {
        value: this.currentCode, // 当前内容
        orig: this.historyCode, // 历史版本
        origLeft: null,
        lineNumbers: true, // 显示行号
        indentUnit: 3, // 缩进吧
        mode: 'html', // 视图文件格式
        highlightDifferences: true, // 高亮
        styleActiveLine: true, // 选中的样式
        connect: 'align', // 居中方式
        theme: 'cobalt', // 视图样式
        readOnly: false, // 只读 不可修改
      });
      this.$nextTick(() => {
        // 获取箭头数量
        const elements = document.getElementsByClassName('CodeMirror-merge-copy');
        this.$emit('getDiff', elements.length);
        // 只能通过父容器事件委托来点击
        const parentElement = document.getElementsByClassName('CodeMirror-merge-copybuttons-right');
        parentElement[0].addEventListener('click', (event) => {
          if (event.target.classList.contains('CodeMirror-merge-copy')) {
            this.$emit('getDiff', elements.length - 1);
          }
        });
      });
    },
  },
};
</script>
<style lang="scss">
.compareClass {
  height: 100%;
  overflow-y: hidden;
  overflow-x: auto;

  .CodeMirror-merge {
    display: flex;
  }

  //.CodeMirror-linenumber {
  //  left: -32px !important;
  //}

  .CodeMirror-merge, .CodeMirror-merge .CodeMirror {
    height: 100vh;
  }

  .CodeMirror-merge-2pane .CodeMirror-merge-pane {
    height: 100%;
  }

  .CodeMirror-merge-r-chunk {
    background: rgba(30, 144, 255, 0.5);
  }

  .CodeMirror-merge-r-chunk-start {
    border-top: 1px solid dodgerblue;
  }

  .CodeMirror-merge-r-chunk-end {
    border-bottom: 1px solid dodgerblue;
  }

  .CodeMirror-merge-r-connect {
    fill: rgba(30, 144, 255, 0.5);
    stroke: rgba(30, 144, 255, 0.5);
    stroke-width: 1px;
  }

  .CodeMirror-merge-l-chunk {
    background: rgba(30, 144, 255, 0.5);
  }

  .CodeMirror-merge-l-chunk-start {
    border-top: 1px solid dodgerblue;
  }

  .CodeMirror-merge-l-chunk-end {
    border-bottom: 1px solid dodgerblue;
  }

  .CodeMirror-merge-l-connect {
    fill: rgba(30, 144, 255, 0.5);
    stroke: rgba(30, 144, 255, 0.5);
    stroke-width: 1px;
  }

  .CodeMirror-merge-l-chunk {
    background: rgba(30, 144, 255, 0.5);
  }

  .CodeMirror-merge-r-chunk {
    background: rgba(30, 144, 255, 0.5);
  }

  .CodeMirror-merge-l-chunk-start {
    border-top: 1px solid dodgerblue;
  }

  .CodeMirror-merge-r-chunk-start {
    border-top: 1px solid dodgerblue;
  }

  .CodeMirror-merge-l-chunk-end {
    border-bottom: 1px solid dodgerblue;
  }

  .CodeMirror-merge-r-chunk-end {
    border-bottom: 1px solid dodgerblue;
  }

}
</style>

3.如果需要反转过来(需求类似于git那种左改右)因为是只支持左侧修改,所以可以通过样式进行翻转,实现效果

上代码

//反转样式
  .CodeMirror-merge-right {
    left: 0px
  }

  .CodeMirror-merge-gap {
    left: 47%;
  }

  .CodeMirror-merge-editor {
    position: absolute;
    right: 0;
  }

  .CodeMirror-merge-copy {
    transform: rotateY(180deg);
    left: 10px !important;
  }
 OK 这样效果就实现了 get get get
转载请注明出处或者链接地址:https://www.qianduange.cn//article/8368.html
标签
stylus
评论
发布的文章

Newtonsoft.Json

2024-05-23 20:05:19

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!