如何使用jsDiff和diff2html库实现类似GitHub的代码比对效果
本文介绍了如何使用jsDiff和diff2html库实现类似GitHub的代码比对效果,能够清晰展示JSON数据的差异,并支持在网页上直观查看变更。提供了HTML和React的实现示例,展示了如何搭建基本的代码比对功能,适用于日常开发中的版本控制和代码变更管理。
背景
在日常开发中,代码比对功能非常重要,特别是涉及到代码变更、版本控制或表单更新时。本文将展示如何使用 jsDiff
和 diff2html
库,实现类似于 GitHub 的代码比对效果,能够清晰地展示 JSON 数据的差异,并且支持在网页上直观查看变更。
技术方案
本次实现将使用两大工具:
- jsDiff:用于生成两个文本的差异结果。
- diff2html:将差异结果格式化并展示为 HTML。
参考资料:
MVP 版本
为了验证该方案的可行性,我们首先使用 HTML + JS
搭建一个简单的 MVP 示例,展示代码比对的基本实现。
HTML Demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>diff2html Example</title>
<!-- 引入diff2html的CSS样式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css">
<!-- 引入diff2html的JavaScript库 -->
<script src="https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js"></script>
<!-- 引入 jsDiff 的JavaScript库 -->
<script src="https://cdn.jsdelivr.net/npm/diff/dist/diff.min.js"></script>
</head>
<body>
<!-- 用于显示差异的容器 -->
<div id="diff-output"></div>
<script>
// 定义两个JSON对象用于比对
const obj1 = { a: 1, b: 2, c: { d: 3 } };
const obj2 = { a: 1, b: 3, c: { d: 4 } };
// 将JSON对象转换为字符串进行比较
const text1 = JSON.stringify(obj1, null, 2);
const text2 = JSON.stringify(obj2, null, 2);
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
// 获取显示差异的DOM元素
var targetElement = document.getElementById('diff-output');
// 生成差异补丁
const diffOutput = Diff.createTwoFilesPatch(
'text1.json', // 左侧文件名
'text2.json', // 右侧文件名
text1, // 左侧内容
text2, // 右侧内容
'', // 补丁标题(可选)
'' // 补丁标题前缀(可选)
);
// 配置 diff2htmlUI 选项
var configuration = {
drawFileList: true, // 是否在差异之前显示文件列表
fileListToggle: false, // 是否允许切换文件列表的显示
fileListStartVisible: false, // 文件列表是否初始时可见
matching: 'lines', // 匹配级别:行
outputFormat: 'side-by-side', // 并排显示的差异格式
synchronizedScroll: true, // 是否同步滚动
highlight: true, // 高亮显示代码
renderNothingWhenEmpty: false // 如果没有差异,是否显示空内容
};
// 初始化 diff2htmlUI 并绘制差异视图
var diff2htmlUi = new Diff2HtmlUI(targetElement, diffOutput, configuration);
diff2htmlUi.draw();
diff2htmlUi.highlightCode();
});
</script>
</body>
</html>
实现效果
在此 HTML 页面中,两个 JSON 对象的差异将以 GitHub 风格的并排视图显示,展示 JSON 对象中的内容更新,方便对比变更。
React 中使用
在实际开发中,往往会使用 React 等框架来实现功能。下面介绍如何在 React 项目中引入 jsDiff
和 diff2html
并实现代码比对功能。
安装依赖
首先,安装相关依赖:
yarn add diff diff2html highlight.js
在 React 中使用
下面是一个在 React 中实现代码比对的示例:
import React, { useEffect, useRef } from 'react';
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'; // diff2html 样式
const DiffComponent = ({ prevData, curData, prevFileName, curFileName }) => {
const diffRef = useRef(null);
useEffect(() => {
const diffOutput = createTwoFilesPatch(
prevFileName, // 左侧文件名
curFileName, // 右侧文件名
JSON.stringify(prevData, null, 2), // 左侧内容
JSON.stringify(curData, null, 2), // 右侧内容
'', '', // 标题和前缀(可选)
);
const targetElement = diffRef.current;
const configuration = {
drawFileList: true,
outputFormat: 'side-by-side', // 并排显示差异
highlight: true,
synchronizeScroll: true,
};
const diff2htmlUi = new Diff2HtmlUI(targetElement, diffOutput, configuration);
diff2htmlUi.draw();
diff2htmlUi.highlightCode();
}, [prevData, curData, prevFileName, curFileName]);
return <div ref={diffRef}></div>;
};
export default DiffComponent;
使用 DiffComponent
在使用该组件时,只需传入要对比的 JSON 数据即可:
const prevJson = { a: 1, b: 2, c: { d: 3 } };
const curJson = { a: 1, b: 3, c: { d: 4 } };
<DiffComponent
prevData={prevJson}
curData={curJson}
prevFileName="prev.json"
curFileName="cur.json"
/>
封装为 Modal 或 Drawer
为了让 DiffComponent
更加灵活,可以将其封装在 Modal
或 Drawer
中,便于弹窗显示代码比对结果:
import { Modal, Button } from 'antd';
const DiffModal = ({ isVisible, onClose, prevData, curData }) => (
<Modal visible={isVisible} onCancel={onClose} footer={null}>
<DiffComponent prevData={prevData} curData={curData} prevFileName="file1.json" curFileName="file2.json" />
</Modal>
);
// 使用
<Button onClick={() => setIsModalVisible(true)}>查看差异</Button>
<DiffModal
isVisible={isModalVisible}
onClose={() => setIsModalVisible(false)}
prevData={prevJson}
curData={curJson}
/>
结尾
通过 jsDiff
和 diff2html
,我们可以轻松实现类似 GitHub 的代码比对效果,并且可以将其灵活地集成到不同的前端项目中。如果您有类似的需求,不妨试试看这个方案。