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

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

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

推荐文章

Python上下文管理器:with语句
2024-11-19 06:25:31 +0800 CST
Vue3中如何处理组件间的动画?
2024-11-17 04:54:49 +0800 CST
CentOS 镜像源配置
2024-11-18 11:28:06 +0800 CST
一文详解回调地狱
2024-11-19 05:05:31 +0800 CST
Vue 中如何处理跨组件通信?
2024-11-17 15:59:54 +0800 CST
Gin 与 Layui 分页 HTML 生成工具
2024-11-19 09:20:21 +0800 CST
维护网站维护费一年多少钱?
2024-11-19 08:05:52 +0800 CST
PHP服务器直传阿里云OSS
2024-11-18 19:04:44 +0800 CST
JS 箭头函数
2024-11-17 19:09:58 +0800 CST
filecmp,一个Python中非常有用的库
2024-11-19 03:23:11 +0800 CST
H5抖音商城小黄车购物系统
2024-11-19 08:04:29 +0800 CST
Nginx rewrite 的用法
2024-11-18 22:59:02 +0800 CST
Vue中的异步更新是如何实现的?
2024-11-18 19:24:29 +0800 CST
禁止调试前端页面代码
2024-11-19 02:17:33 +0800 CST
PHP设计模式:单例模式
2024-11-18 18:31:43 +0800 CST
Python 获取网络时间和本地时间
2024-11-18 21:53:35 +0800 CST
前端项目中图片的使用规范
2024-11-19 09:30:04 +0800 CST
程序员茄子在线接单