编程 如何使用jsDiff和diff2html库实现类似GitHub的代码比对效果

2024-11-18 20:11:51 +0800 CST views 1001

如何使用jsDiff和diff2html库实现类似GitHub的代码比对效果

本文介绍了如何使用jsDiff和diff2html库实现类似GitHub的代码比对效果,能够清晰展示JSON数据的差异,并支持在网页上直观查看变更。提供了HTML和React的实现示例,展示了如何搭建基本的代码比对功能,适用于日常开发中的版本控制和代码变更管理。

背景

在日常开发中,代码比对功能非常重要,特别是涉及到代码变更、版本控制或表单更新时。本文将展示如何使用 jsDiffdiff2html 库,实现类似于 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 项目中引入 jsDiffdiff2html 并实现代码比对功能。

安装依赖

首先,安装相关依赖:

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 更加灵活,可以将其封装在 ModalDrawer 中,便于弹窗显示代码比对结果:

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}
/>

结尾

通过 jsDiffdiff2html,我们可以轻松实现类似 GitHub 的代码比对效果,并且可以将其灵活地集成到不同的前端项目中。如果您有类似的需求,不妨试试看这个方案。

推荐文章

windows安装sphinx3.0.3(中文检索)
2024-11-17 05:23:31 +0800 CST
Golang 随机公平库 satmihir/fair
2024-11-19 03:28:37 +0800 CST
File 和 Blob 的区别
2024-11-18 23:11:46 +0800 CST
php strpos查找字符串性能对比
2024-11-19 08:15:16 +0800 CST
mysql 优化指南
2024-11-18 21:01:24 +0800 CST
介绍25个常用的正则表达式
2024-11-18 12:43:00 +0800 CST
Vue中的表单处理有哪几种方式?
2024-11-18 01:32:42 +0800 CST
一文详解回调地狱
2024-11-19 05:05:31 +0800 CST
php内置函数除法取整和取余数
2024-11-19 10:11:51 +0800 CST
Vue3中的组件通信方式有哪些?
2024-11-17 04:17:57 +0800 CST
php腾讯云发送短信
2024-11-18 13:50:11 +0800 CST
Vue 3 中的 Fragments 是什么?
2024-11-17 17:05:46 +0800 CST
使用 Go Embed
2024-11-19 02:54:20 +0800 CST
go错误处理
2024-11-18 18:17:38 +0800 CST
Nginx 状态监控与日志分析
2024-11-19 09:36:18 +0800 CST
Go语言SQL操作实战
2024-11-18 19:30:51 +0800 CST
从Go开发者的视角看Rust
2024-11-18 11:49:49 +0800 CST
FcDesigner:低代码表单设计平台
2024-11-19 03:50:18 +0800 CST
程序员茄子在线接单