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

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

如何使用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 的代码比对效果,并且可以将其灵活地集成到不同的前端项目中。如果您有类似的需求,不妨试试看这个方案。

推荐文章

robots.txt 的写法及用法
2024-11-19 01:44:21 +0800 CST
小技巧vscode去除空格方法
2024-11-17 05:00:30 +0800 CST
Golang Select 的使用及基本实现
2024-11-18 13:48:21 +0800 CST
html流光登陆页面
2024-11-18 15:36:18 +0800 CST
PHP 8.4 中的新数组函数
2024-11-19 08:33:52 +0800 CST
Python设计模式之工厂模式详解
2024-11-19 09:36:23 +0800 CST
Flet 构建跨平台应用的 Python 框架
2025-03-21 08:40:53 +0800 CST
从Go开发者的视角看Rust
2024-11-18 11:49:49 +0800 CST
Plyr.js 播放器介绍
2024-11-18 12:39:35 +0800 CST
Dropzone.js实现文件拖放上传功能
2024-11-18 18:28:02 +0800 CST
Graphene:一个无敌的 Python 库!
2024-11-19 04:32:49 +0800 CST
liunx宝塔php7.3安装mongodb扩展
2024-11-17 11:56:14 +0800 CST
Vue3中的事件处理方式有何变化?
2024-11-17 17:10:29 +0800 CST
介绍 Vue 3 中的新的 `emits` 选项
2024-11-17 04:45:50 +0800 CST
html一些比较人使用的技巧和代码
2024-11-17 05:05:01 +0800 CST
vue打包后如何进行调试错误
2024-11-17 18:20:37 +0800 CST
Vue3 中提供了哪些新的指令
2024-11-19 01:48:20 +0800 CST
php机器学习神经网络库
2024-11-19 09:03:47 +0800 CST
乐观锁和悲观锁,如何区分?
2024-11-19 09:36:53 +0800 CST
php使用文件锁解决少量并发问题
2024-11-17 05:07:57 +0800 CST
mysql删除重复数据
2024-11-19 03:19:52 +0800 CST
程序员茄子在线接单