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

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

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

推荐文章

Shell 里给变量赋值为多行文本
2024-11-18 20:25:45 +0800 CST
网站日志分析脚本
2024-11-19 03:48:35 +0800 CST
JavaScript设计模式:组合模式
2024-11-18 11:14:46 +0800 CST
前端如何给页面添加水印
2024-11-19 07:12:56 +0800 CST
Go中使用依赖注入的实用技巧
2024-11-19 00:24:20 +0800 CST
IP地址获取函数
2024-11-19 00:03:29 +0800 CST
ElasticSearch 结构
2024-11-18 10:05:24 +0800 CST
在 Docker 中部署 Vue 开发环境
2024-11-18 15:04:41 +0800 CST
js一键生成随机颜色:randomColor
2024-11-18 10:13:44 +0800 CST
CentOS 镜像源配置
2024-11-18 11:28:06 +0800 CST
Nginx 跨域处理配置
2024-11-18 16:51:51 +0800 CST
开发外贸客户的推荐网站
2024-11-17 04:44:05 +0800 CST
使用 `nohup` 命令的概述及案例
2024-11-18 08:18:36 +0800 CST
程序员茄子在线接单