前情提要
場景: 產(chǎn)品要求實現(xiàn)兩個json的前后對比的功能麸俘,以提供快速查看修改內(nèi)容穷躁,類似于vscode里面的working tree.
問題: 既然功能類似于vscode,而vscode的底層代碼編輯器就是monaco editor,所以利用微軟出的基于瀏覽器的編輯器monaco
來實現(xiàn)需求~
基礎(chǔ)步驟
- 安裝
monaco editor
npm install monaco-editor -S
- 引入并初始化實例
創(chuàng)建一個container
<template>
<div
ref="container"
class="monaco-editor"
:style="'height: ' + height + 'px'"
></div>
</template>
引入monaco 初始化這個container
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
let originalModel;
let modifiedModel;
let monacoDiffInstance;
const container = ref(null);
function init() {
// 初始化編輯器實例
monacoDiffInstance = monaco.editor.createDiffEditor(
container.value,
//配置項
defaultOpts
);
originalModel = monaco.editor.createModel(
oldValue,
'json'
);
modifiedModel = monaco.editor.createModel(
newvalue,
'json'
);
monacoDiffInstance.setModel({
original: originalModel,
modified: modifiedModel,
});
}
在做編輯器實例的初始化時狞山,定義originalModel
modifiedModel
monacoDiffInstance
變量時码泞,使用ref()
或reactive()
來定義上述響應(yīng)式變量都無法生效吱涉,這里如果有懂的大神可以指教一下..
- 設(shè)置配置項
const defaultOpts = reactive({
value: "",
theme: "vs", // 編輯器主題:vs, hc-black, or vs-dark逛薇,更多選擇詳見官網(wǎng)https://microsoft.github.io/monaco-editor/docs.html
roundedSelection: false, // 右側(cè)不顯示編輯器預(yù)覽框
autoIndent: true, // 自動縮進
readOnly: true, // 是否只讀
diffWordWrap:true,
wordWrap:'on',
automaticLayout:true,
scrollBeyondLastLine:false,
scrollbar:{
verticalScrollbarSize: 0
},
});
這里吐槽一下..這個官方文檔實在是太難讀了捺疼,想要通過配置修改一個很簡單的功能要在里面繞半天..給大家推薦一個中文版文檔雖然也不是特別好找但是最起碼先解決了language的問題????https://aydk.site/editor/
封裝組件
以上已經(jīng)實現(xiàn)了最基本的對比編輯器的功能了,接下來封裝就是基礎(chǔ)操作了~
// desc: 基于monaco的diff editor
// feat:支持Json文件對比
// usage: <diffEditor
// ref="monacoContainer"
// :oldValue="oldValue" //舊值
// :value="value" //新值
// :visible="editorVisible"
// style="width: 100%"
// ></diffEditor>
<template>
<div
ref="container"
class="monaco-editor"
:style="'height: ' + height + 'px'"
></div>
</template>
<script setup>
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
import {
defineProps,
reactive,
ref,
defineEmits,
watch,
nextTick,
onBeforeUnmount,
} from "vue";
const props = defineProps({
language: {
type: String,
default: "json",
},
oldValue: String,
value: String,
visible: Boolean,
height: {
type: Number,
default: 380,
},
});
watch(
() => props.oldValue,
(newValue) => {
originalModel = monaco.editor.createModel(newValue, props.language);
monacoDiffInstance.setModel({
original: originalModel,
modified: modifiedModel,
});
},
{ deep: true }
);
watch(
() => props.value,
(newValue) => {
modifiedModel = monaco.editor.createModel(newValue, props.language);
monacoDiffInstance.setModel({
original: originalModel,
modified: modifiedModel,
});
},
{ deep: true }
);
watch(
() => props.visible,
(newValue) => {
newValue && nextTick(()=>{init()})
},
{
immediate: true,
}
);
const defaultOpts = reactive({
value: "",
theme: "IDLE", // 編輯器主題:vs, hc-black, or vs-dark永罚,更多選擇詳見官網(wǎng)
roundedSelection: false, // 右側(cè)不顯示編輯器預(yù)覽框
autoIndent: true, // 自動縮進
readOnly: true, // 是否只讀
diffWordWrap:true,
wordWrap:'on',
automaticLayout:true,
scrollBeyondLastLine:false,
scrollbar:{
verticalScrollbarSize: 0
},
});
let originalModel;
let modifiedModel;
let monacoDiffInstance;
const container = ref(null);
function init() {
monaco.editor.defineTheme('IDLE', Theme);
monaco.editor.setTheme('IDLE')
// 初始化編輯器實例
monacoDiffInstance = monaco.editor.createDiffEditor(
container.value,
defaultOpts
);
originalModel = monaco.editor.createModel(
JSON.stringify(JSON.parse(props.oldValue), null, "\t"),
props.language
);
modifiedModel = monaco.editor.createModel(
JSON.stringify(JSON.parse(props.value), null, "\t"),
props.language
);
monacoDiffInstance.setModel({
original: originalModel,
modified: modifiedModel,
});
}
onBeforeUnmount(()=>{
monacoDiffInstance.dispose()
})
</script>
<style lang="less">
.the-code-diff-editor-container {
width: 100%;
height: 100%;
overflow: auto;
.monaco-editor .scroll-decoration {
box-shadow: none;
}
}
</style>
OK~~~完結(jié)撒花??...