背景
在最近的开发过程需要实现两条数据的对比效果,方便客户使用,看了一下市场上有比较不少完整的插件,就选择了其中一种来实现
技术选型
插件: jsDiff + diff2html
框架:vue3+elementplus
实现功能及效果图:
通过点击事件实现弹框展示两条数据对比
1.下载相关依赖
yarn add diff
yarn add diff2html
yarn add @types/diff
2.html部分
<template>
<el-button plain @click="openDiff"> Click to open the diffDialog </el-button>
<el-dialog
v-model="dialogVisible"
title="Tips"
width="900"
:before-close="handleClose"
>
<div ref="diffContainer"></div>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="dialogVisible = false">
Confirm
</el-button>
</div>
</template>
</el-dialog>
</template>
3.js实现部分
注意:在弹框中展示需要nextTick回调等弹框渲染完毕后再获取节点,在执行draw方法渲染
<script setup lang="ts">
import { ElDialog, ElButton } from "element-plus";
import { ref, nextTick } from "vue";
import { createTwoFilesPatch } from "diff";
import { Diff2HtmlUI } from "diff2html/lib/ui/js/diff2html-ui";
import "highlight.js/styles/googlecode.css";
import "diff2html/bundles/css/diff2html.min.css";
const dialogVisible = ref(false);
const handleClose = () => {};
// 差异字符串(通常通过diff算法生成)
// 定义两个JSON对象(作为示例)
const obj1 = { a: "牛魔王", b: 2, c: { d: 3 } };
const obj2 = { a: "胡图图", b: 3, c: { d: 4 } };
// 将JSON对象转换为字符串进行比较
const text1 = JSON.stringify(obj1, null, 2);
const text2 = JSON.stringify(obj2, null, 2);
const diffContainer = ref<HTMLElement | null>(null);
let configuration = {
drawFileList: true, // 是否在差异之前显示文件列表
fileListToggle: false, // 是否允许切换文件列表的显示
fileListStartVisible: false, // 文件列表是否初始时可见
matching: "lines", // 匹配级别:行
outputFormat: "side-by-side", // 输出格式:并排显示
synchronizedScroll: true, // 同步滚动(并排模式)
highlight: true, // 是否高亮显示代码
renderNothingWhenEmpty: false, // 如果没有差异,是否渲染空内容
};
//diff代码比对
const openDiff = () => {
dialogVisible.value = true;
const diffOutput = createTwoFilesPatch(
"text1.json",
"text2.json",
text1,
text2
);
console.log(diffOutput);
// 初始化diff2htmlUI并配置
// 创建并绘制diff
//dom更新之后再执行比较,否则查询不到dom节点 直接报错
nextTick(() => {
if (diffContainer.value) {
let diff2htmlUi = new Diff2HtmlUI(
diffContainer.value, //渲染节点
diffOutput, //内容
configuration //配置项
);
diff2htmlUi.draw();
diff2htmlUi.highlightCode();
}
});
};
</script>
效果图如下
补充
在弹框中如果数据过多,可能导致右侧序号不滚动,左侧代码内容滚动问题 是因为 .d2h-code-side-linenumber 样式设置了绝对定位导致。
样式错乱图如下 左侧序号跟右侧代码内容不对照
解决思路
:deep(.d2h-code-side-linenumber) {
position: relative;
}