需求:
- 两个文本进行比对差异
- 比对结果像git change 一样展示
- 自由限定文本间的差异
进程:
- 查找到相应的控件
- diff diff2html
- npm install diff npm install diff2html
- diff 可以对比两个文本, diff2html 可以将对比结果渲染成html
-
import { createPatch } from "diff";
diff 还有其他的方法,diffWords, diffjson 等,不过返回的格式是一个正常的json,并不是patch
-
import { html, parse } from "diff2html"; import "diff2html/bundles/css/diff2html.min.css"; import { Diff2HtmlUI } from "diff2html/lib/ui/js/diff2html-ui";
diff2html 需要引用自带的css
-
diff2html 参考https://github.com/rtfpessoa/diff2html#usage
-
parse 可以将diff 出来的patch 转换成自己可用的格式
-
html 可以将parse 出来的json 展示成对应的html
-
let oldString = JSON.stringify(oldContent, null, 2); let newString = JSON.stringify(newContent, null, 2); let args = [ "", oldString, newString, "", "", { context: moreLine } ]; const diffStr = createPatch(...args); const diffJson = parse(diffStr); const diffHtml = html(diffJsonList, { drawFileList: true, matching: "lines", showFiles: false, outputFormat: "side-by-side" });
最后只要再做一次渲染就可以了
-
如果使用Diff2HtmlUI 相对于 html 他有更多的功能
-
let oldString = JSON.stringify(oldContent, null, 2); let newString = JSON.stringify(newContent, null, 2); let args = [ "", oldString, newString, "", "", { context: moreLine } ]; const diffStr = createPatch(...args); const diffJson = parse(diffStr); const targetElement = document.getElementById(id); const diff2htmlUi = new Diff2HtmlUI(targetElement, diffJsonList, { drawFileList: true, matching: "lines", showFiles: false, outputFormat: "side-by-side" }); diff2htmlUi.draw(); //绘制页面 diff2htmlUi.highlightCode(); // 高亮数据 diff2htmlUi.fileListToggle(fileListToggle);
-
<div dangerouslySetInnerHTML={{__html: diffHtml }}/>
结果展示:
完整的代码块 :
import React, {useEffect, useState} from 'react';
import { createPatch } from "diff";
import { html, parse } from "diff2html";
import "diff2html/bundles/css/diff2html.min.css";
import "./index.less"
export type ContentDiffProps = {
oldContent: string;
newContent: string;
moreLine: number;
}
const ContentDiff: React.FC<ContentDiffProps> = (props) => {
const [ diffData, setDiffData ] = useState("");
const diffJsonList = [];
const {oldContent, newContent, moreLine} = props;
useEffect(() => {
createDiffData();
}, [oldContent, newContent, moreLine]);
const createDiffData = () => {
let oldString = JSON.stringify(oldContent, null, 2);
let newString = JSON.stringify(newContent, null, 2);
let args = [ "", oldString, newString, "", "", { context: moreLine } ];
const diffStr = createPatch(...args);
// 差异json化
const diffJson = parse(diffStr);
diffJsonList.push(diffJson[0]);
const diffHtml = html(diffJsonList, {
drawFileList: true, matching: "lines", showFiles: false, outputFormat: "side-by-side"
});
setDiffData(diffHtml);
}
return (
<div dangerouslySetInnerHTML={{__html: diffData}}/>
)
}
export default ContentDiff;