如何實現 github 代碼比對效果?
背景
背景是我想要做一個類似於 github 的代碼比對的效果,方便我後續做表單更新的時候,通過 Json View 可以很清晰的看到變更,所以需要做這麼一個東西,看了一下市面上有不少比較完整的插件,所以就選擇了其中的一種來實現,整體做下來還是很快的。
本篇文章主要聚焦於 “實現”,後續可能會寫一篇文章去聊diff
代碼比對的原理
技術方案
「技術選型:jsDiff + diff2html」
-
參考:
-
如何實現 git-diff 效果
-
GitHub - rtfpessoa/diff2html: Pretty diff to html javascript library (diff2html)
Html Demo
爲了驗證這個方案的可行性,我用 HTML + JS 做了一個 MVP 版本,代碼和配置還有最後的實現細節效果都如下,整體感覺沒啥問題。
<!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>
// 差異字符串(通常通過diff算法生成)
// 定義兩個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 // 如果沒有差異,是否渲染空內容
};
// 創建並繪製diff
var diff2htmlUi = new Diff2HtmlUI(targetElement, diffOutput, configuration);
diff2htmlUi.draw();
diff2htmlUi.highlightCode();
});
</script>
</body>
</html>
「實現效果:」
React 中使用
只實現一個 HTML DEMO 肯定遠遠不夠,我們需要實際落地的話,就得使用 React 來實現。
- 下載相關依賴
yarn diff
yarn diff2html
- 需要關注一下引入路徑:不僅僅是處理 diff 文件的引入路徑,diff 的樣式的引入路徑也同樣需要關注,可以簡單看看,列舉如下:
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';
- 使用設計好的組件
<DiffComponent
prevData={code1}
curData={code2}
prevFileName={code1Name}
curFileName={code2Name}
/>
這裏的話其實還值得一提:可以在這裏結合Modal/Drawer
把DiffComponent
封裝一下,當然封裝的過程少不了改組件本身的樣式,因爲常見的使用位置是在一個頁面上,但我們有些常見是需要封裝在 Modal 和 Drawer 裏面的。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/lqNO9W6VsYqEwbvmy7rePQ