需求:在页面中实现一个json编辑器和实现一个json文件对比并且显示差异
json编译器效果图如下

代码对比效果图如下

实现代码
npm i -S vue-codemirror codemirror
npm i -S diff-match-patch
新建一个JsonEditor.vue文件
<template>
<div class="json-editor">
<codemirror
ref="myCode"
:value="value"
:options="codeOptions"
@input="inputValue"
></codemirror>
</div>
</template>
<script>
import { codemirror } from "vue-codemirror";
import "codemirror/addon/lint/lint.css";
import "codemirror/lib/codemirror.css";
import "codemirror/theme/rubyblue.css";
require("script-loader!jsonlint");
import "codemirror/mode/javascript/javascript";
import "codemirror/addon/lint/lint";
import "codemirror/addon/lint/json-lint";
import "codemirror/mode/htmlmixed/htmlmixed.js";
import "codemirror/addon/selection/active-line.js";
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/comment-fold.js";
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/indent-fold.js";
import "codemirror/addon/fold/markdown-fold.js";
import "codemirror/addon/fold/xml-fold.js";
export default {
name: "JsonEditor",
props: {
value: {
type: String,
default: "",
},
disabled: {
type: Boolean,
default: false,
},
},
components: {
codemirror,
},
data() {
return {
codeOptions: {
autoRefresh: true,
mode: "application/json",
gutters: ["CodeMirror-lint-markers", "CodeMirror-foldgutter"],
lint: true,
foldGutter: true,
lineNumbers: true,
smartIndent: true,
cursorBlinkRate: 350,
},
};
},
methods: {
inputValue(value) {
this.$emit("changed", value);
},
},
watch: {
disabled: {
handler(v) {
this.codeOptions.readOnly = v;
if (v) {
this.codeOptions.cursorBlinkRate = -1;
this.codeOptions.lint = false;
this.codeOptions.theme = "baspin"
} else {
this.codeOptions.cursorBlinkRate = 350;
this.codeOptions.lint = true;
}
},
immediate: true,
},
},
};
</script>
<style lang="scss" scoped>
.json-editor {
// height: 400px;
position: relative;
display: flex;
flex-direction: column;
::v-deep {
.CodeMirror {
flex: 1;
border: 1px solid #efefef ;
}
.CodeMirror-scroll {
max-height: 400px;
}
.cm-s-rubyblue span.cm-string {
color: #f08047;
}
}
}
</style>
父组件使用
import JsonEditor from "@/components/JsonEditor";
<json-editor
ref="jsonEditor"
v-model="appConfig"
@changed="changeValue"
:disabled="!editFlag"/>
小tips 获取编译器鼠标位置 ,并且往编译器插入文本了
let pos1 = this.$refs.myCode.codemirror.getCursor();
let pos2 = {};
pos2.line = pos1.line;
pos2.ch = pos1.ch;
this.$refs.myCode.codemirror.replaceRange(value, pos2);
代码对比
新建一个CodeCompare.vue 文件
<template>
<div id="contrastDiv">
<div ref="contrastDiv"></div>
</div>
</template>
<script>
require("codemirror/mode/javascript/javascript.js");
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";
window.diff_match_patch = DiffMatchPatch;
window.DIFF_DELETE = -1;
window.DIFF_INSERT = 1;
window.DIFF_EQUAL = 0;
export default {
name: "CodeMirror",
props: {
oldVal: {
default: "",
},
newVal: {
default: "",
},
},
watch: {
newVal(val) {
this.contrast();
},
},
mounted() {
this.prepareData();
this.contrast();
},
methods: {
prepareData() {},
contrast() {
this.$nextTick(() => {
const target = this.$refs.contrastDiv;
target.innerHTML = "";
CodeMirror.MergeView(target, {
value: this.prettyJson(this.oldVal) ?? "",
orig: this.prettyJson(this.newVal) ?? "",
lineNumbers: true,
mode: "text/html",
highlightDifferences: true,
connect: "align",
readOnly: true,
});
});
},
prettyJson(json) {
return JSON.stringify(json, null, 2);
},
},
};
</script>
<style lang="scss">
.compareClass {
height: 100%;
overflow-y: auto;
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>
对比的时候对比的是文本 将json文件JSON.parse格式化一下然后再转为文本对比
<el-row class="version-notice">
<el-col :span="12"><span>当前版本</span></el-col>
<el-col :span="12"><span>历史版本</span></el-col>
</el-row>
<code-compare :oldVal="editCodeValue" :newVal="newCodeValue" :isReadOnly="true" class="compare-box"/>