react项目配合diff实现文件对比差异功能

效果图:

在这里插入图片描述
这是点击一个按钮随后显示一个Modal弹框,分为上中下三部分。
首先我们需要下载一个依赖包diff

npm install diff --save

这个引入的方式只能使用commonJS的形式引入,而不能使用ES6的形式引入

const Diff = require('diff');

里面涉及到的方法很多:

参考链接 :https://maokun.blog.csdn.net/article/details/104092182

我这里只用到了其中一个对比方法:

Diff.diffChars(oldStr, newStr[, options]) 

options:ignoreCase:true忽略大小写差异。默认为false。

返回值 :
在这里插入图片描述
分析:
在这里插入图片描述
返回数组对象,每个对象都有count和value属性
count:字符个数;
value:具体字符;
新增或者删除的对象属性:
added:新增标识,新增为true,否为undefined;
renoved:删除标识,删除为true,否为undefined;

基本使用版本:
拿来的例子
就是将读出来的数组进行循环,随后创建标签,最后整体追加到页面中进行展示。
在html中:

<pre id="display"></pre>
<script src="diff.js"></script>
<script>
var one = 'beep boop',
    other = 'beep boob blah',
    color = '',
    span = null;
 
var diff = Diff.diffChars(one, other),
    display = document.getElementById('display'),
    fragment = document.createDocumentFragment();
 
diff.forEach(function(part){
    
    
  // green for additions, red for deletions
  // grey for common parts
  color = part.added ? 'green' :
    part.removed ? 'red' : 'grey';
  span = document.createElement('span');
  span.style.color = color;
  span.appendChild(document
    .createTextNode(part.value));
  fragment.appendChild(span);
});
 
display.appendChild(fragment);
</script>

react第一版

此外我们还可以看到读文件后读出的换行符,所有我们还能根据这个换行符对整理好的数据进行展示:

import React, {
    
     Fragment } from 'react'
import {
    
     Modal, Divider, Spin } from 'antd';
import RSButton from '@com/RSButton'
const Diff = require('diff');
export default class DiffString extends React.Component {
    
    
    static defaultProps = {
    
    
        isModalVisible: false,
        title: "预览文件差异",
        changeIsModalVisibleState: () => {
    
     },
        oldStr: "",
        newStr: "",
        contextBoxLoading: false,
    }
    /**
     * oldStr  为上次文件
     * 
     * newStr 为最新文件 
     * 
     * contextBoxLoading  加载文件的loading
     * 
     * isModalVisible modal显示与否
     * 
     */

    handleCancel() {
    
    
        this.props.changeIsModalVisibleState()
    }
    render() {
    
    
        let {
    
     title, width, isModalVisible, contextBoxLoading, oldStr ,newStr, ...rest } = this.props
        console.log(Diff.diffChars(oldStr, newStr))
        return (
           <Modal
                title={
    
    <div>{
    
    title}<h4 style={
    
    {
    
     float: "right" }}>灰色:<span style={
    
    {
    
     color: "grey" }}>无变化</span>;绿色:<span style={
    
    {
    
     color: "green" }}>新增</span>;红色:<span style={
    
    {
    
     color: "red" }}>删除</span></h4></div>}
                visible={
    
    isModalVisible}
                maskClosable={
    
    true}
                style={
    
    {
    
     top: "20%", minWidth: "1000px" }}
                closable={
    
    false}
                width={
    
    width}
                {
    
    ...rest}
                footer={
    
    [
                    <RSButton rsType="noIcon" key={
    
    1} title="关闭" onClick={
    
    () => this.handleCancel()}></RSButton>
                ]}
            >
                <Spin tip="配置文件获取中..." spinning={
    
    contextBoxLoading} size="large" style={
    
    {
    
     width: "100%", height: '100%' }}>
                    <div style={
    
    {
    
     height: "600px", overflowY: "scroll" }}>
                        <div style={
    
    {
    
     wordBreak: "break-all", display: "flex" }}>
                            <div style={
    
    {
    
     width: "50%", paddingLeft: "30px" }}>
                                <h2 style={
    
    {
    
     fontWeight: "700" }}>已生效配置</h2>
                                {
    
    Diff.diffWordsWithSpace(newStr, oldStr).map((item, index) => {
    
    
                                    return (
                                        <Fragment key={
    
    index} >
                                            <span style={
    
    {
    
    
                                                fontSize: "0",
                                                marginBottom: "0",
                                                padding: "0",
                                                lineHeight: "40px",
                                                color: item.added ? 'red' :
                                                    item.removed ? 'green' : 'grey',
                                                fontWeight: item.added ? '600' :
                                                    item.removed ? '600' : 'normal',
                                            }}>{
    
    !item ? null : item.removed ? null : item.value.split('\n').map((i, indexx) => {
    
    
                                                return <Fragment key={
    
    indexx} >
                                                    {
    
    i && <span style={
    
    {
    
     marginBottom: "0", lineHeight: "22px", fontSize: "16px", whiteSpace: "pre" }} key={
    
    indexx}>{
    
    i}</span>}
                                                    {
    
    indexx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                </Fragment>
                                            })} </span>
                                        </Fragment>
                                    )
                                })}
                            </div>
                            <Divider type="vertical" style={
    
    {
    
     width: "10px", height: "auto" }} />
                            <div style={
    
    {
    
     flex: "1", paddingLeft: "20px" }}>
                                <h2 style={
    
    {
    
     fontWeight: "700" }}>待下发</h2>
                                {
    
    Diff.diffWordsWithSpace(oldStr, newStr).map((item, index) => {
    
    
                                    return (
                                        <Fragment key={
    
    index} >
                                            <span style={
    
    {
    
    
                                                fontSize: "0",
                                                marginBottom: "0",
                                                padding: "0",
                                                lineHeight: "40px",
                                                color: item.added ? 'green' :
                                                    item.removed ? 'red' : 'grey',
                                                fontWeight: item.added ? '600' :
                                                    item.removed ? '600' : 'normal',
                                            }}>{
    
    !item ? null : item.removed ? null : item.value.split('\n').map((i, indexx) => {
    
    
                                                return <Fragment key={
    
    indexx} >
                                                    {
    
    console.log(i, item)}
                                                    {
    
    i && <span style={
    
    {
    
     marginBottom: "0", lineHeight: "22px", fontSize: "16px", whiteSpace: "pre" }} key={
    
    indexx}>{
    
    i}</span>}
                                                    {
    
    indexx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                </Fragment>
                                            })} </span>
                                        </Fragment>
                                    )
                                })}
                            </div>

                        </div>
                    </div>
                </Spin>
            </Modal>
        )
    }
}

这里其实已经封装成了一个组件,使用了antd的Modal组件。
里面也是对数据进行循环,对样式进行控制,对内容进行切割,换行展示。

react第二版

最终我选择了使用行比较,最终代码如下,本人最终目的是为了留笔记,所以直接粘贴代码了:

/*
 * @Descripttion: 
 * @version: 
 * @Author: ZhangJunQing
 * @Date: 2021-11-12 17:35:44
 * @LastEditors: ZhangJunQing
 * @LastEditTime: 2022-01-12 15:08:08
 */
import React, {
    
     Fragment } from 'react'
import {
    
     Modal, Divider, Spin } from 'antd';
import RSButton from '@com/RSButton'
const Diff = require('diff');
export default class DiffString extends React.Component {
    
    
    static defaultProps = {
    
    
        isModalVisible: false,
        title: "预览文件差异",
        changeIsModalVisibleState: () => {
    
     },
        oldStr: "",
        newStr: "",
        contextBoxLoading: false,
    }
    /**
     * oldStr  为上次文件  已生效配置
     * 
     * newStr 为最新文件  待下发
     * 
     * contextBoxLoading  加载文件的loading
     * 
     * isModalVisible modal显示与否
     * 
     */
    state = {
    
    
        isSplitBRFlag: true,//是否为 对齐查看   这个变量目前不做动态改变  和changeisSplitBRFlagFun方法配合
        isOriginFlag: false
    }
    // 源文件切换变量
    changeOriginFileFun = () => {
    
    
        this.setState({
    
    
            isOriginFlag: !this.state.isOriginFlag
        })
    }
    // 是否为 对齐查看   
    changeisSplitBRFlagFun = () => {
    
    
        this.setState({
    
    
            isSplitBRFlag: !this.state.isSplitBRFlag
        })
    }
    handleCancel() {
    
    
        this.props.changeIsModalVisibleState()
    }
    render() {
    
    
        let {
    
     isSplitBRFlag, isOriginFlag } = this.state
        let {
    
     title, width, isModalVisible, contextBoxLoading, oldStr, newStr, ...rest } = this.props
        // console.log(Diff.diffLines(oldStr.replace(/\r/ig, ''), newStr.replace(/\r/ig, '')), "zjqqq")
        return (
            <Modal
                title={
    
    <div>{
    
    title}<h4 style={
    
    {
    
     float: "right" }}>灰色:<span style={
    
    {
    
     color: "grey" }}>无变化</span>;绿色:<span style={
    
    {
    
     color: "green" }}>新增</span>;红色:<span style={
    
    {
    
     color: "red" }}>删除</span></h4></div>}
                visible={
    
    isModalVisible}
                maskClosable={
    
    true}
                style={
    
    {
    
     top: "20%", minWidth: "1000px" }}
                closable={
    
    false}
                width={
    
    width}
                {
    
    ...rest}
                footer={
    
    [
                    <RSButton rsType="noIcon" key={
    
    1} title={
    
    !isOriginFlag ? "切换源文件" : "切换对比文件"} onClick={
    
    () => this.changeOriginFileFun()}></RSButton>,
                    <RSButton rsType="noIcon" key={
    
    2} title="关闭" onClick={
    
    () => this.handleCancel()}></RSButton>
                ]}
            >
                <Spin tip="配置文件获取中..." spinning={
    
    contextBoxLoading} size="large" style={
    
    {
    
     width: "100%", height: '100%' }}>
                    <div style={
    
    {
    
     height: "600px", overflowY: "scroll" }}>
                        <div style={
    
    {
    
     wordBreak: "break-all", display: "flex" }}>
                            <div style={
    
    {
    
     width: "50%", paddingLeft: "30px" }}>
                                <h2 style={
    
    {
    
     fontWeight: "700" }}>已生效配置</h2>
                                {
    
    Diff.diffLines(oldStr.replace(/\r/ig, ''), isOriginFlag ? oldStr.replace(/\r/ig, '') : newStr.replace(/\r/ig, '')).map((item, index) => {
    
    
                                    return (
                                        <Fragment key={
    
    index} >
                                            <span style={
    
    {
    
    
                                                fontSize: "0",
                                                marginBottom: "0",
                                                padding: "0",
                                                lineHeight: "40px",
                                                color: item.added ? 'green' :
                                                    item.removed ? 'red' : 'grey',
                                                fontWeight: item.added ? '600' :
                                                    item.removed ? '600' : '600',
                                            }}>{
    
    !item ? null : item.added ? (isSplitBRFlag ?
                                                item.value.split('\n').map((child, idx) => {
    
    
                                                    return <Fragment key={
    
    idx} >
                                                        {
    
    child && <span style={
    
    {
    
     marginBottom: "0", lineHeight: "22px", fontSize: "16px", whiteSpace: "pre", color: "transparent", userSelect: "none" }} key={
    
    idx}>{
    
    child}</span>}
                                                        {
    
    idx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                    </Fragment>
                                                }) : null)
                                                : item.value.split('\n').map((i, indexx) => {
    
    
                                                    return <Fragment key={
    
    indexx} >
                                                        {
    
    i && <span style={
    
    {
    
     marginBottom: "0", lineHeight: "22px", fontSize: "16px", whiteSpace: "pre" }} key={
    
    indexx}>{
    
    i}</span>}
                                                        {
    
    indexx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                    </Fragment>
                                                })} </span>
                                        </Fragment>
                                    )
                                })}
                            </div>
                            <Divider type="vertical" style={
    
    {
    
     width: "10px", height: "auto", minHeight: '600px' }} />
                            <div style={
    
    {
    
     flex: "1", paddingLeft: "20px" }}>
                                <h2 style={
    
    {
    
     fontWeight: "700" }}>待下发</h2>
                                {
    
    Diff.diffLines(isOriginFlag ? newStr.replace(/\r/ig, '') : oldStr.replace(/\r/ig, ''), newStr.replace(/\r/ig, '')).map((item, index) => {
    
    
                                    return (
                                        <Fragment key={
    
    index} >
                                            <span style={
    
    {
    
    
                                                fontSize: "0",
                                                marginBottom: "0",
                                                padding: "0",
                                                lineHeight: "40px",
                                                color: item.added ? 'green' :
                                                    item.removed ? 'red' : 'grey',
                                                fontWeight: item.added ? '600' :
                                                    item.removed ? '600' : '600',
                                            }}>{
    
    !item ? null : item.removed ? (isSplitBRFlag ?
                                                item.value.split('\n').map((child, idx) => {
    
    
                                                    return <Fragment key={
    
    idx} >
                                                        {
    
    child && <span style={
    
    {
    
     marginBottom: "0", lineHeight: "22px", fontSize: "16px", whiteSpace: "pre", color: "transparent", userSelect: "none" }} key={
    
    idx}>{
    
    child}</span>}
                                                        {
    
    idx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                    </Fragment>
                                                }) : null)
                                                : item.value.split('\n').map((i, indexx) => {
    
    
                                                    return <Fragment key={
    
    indexx} >
                                                        {
    
    i && <span style={
    
    {
    
     marginBottom: "0", lineHeight: "22px", fontSize: "16px", whiteSpace: "pre" }} key={
    
    indexx}>{
    
    i}</span>}
                                                        {
    
    indexx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                    </Fragment>
                                                })} </span>
                                        </Fragment>
                                    )
                                })}
                            </div>

                        </div>
                    </div>
                </Spin>
            </Modal>
        )
    }
}


在这里插入图片描述

上面做了两个操作 一个是切换源文件,就是只看两个文件,这个也进行了对比,目的是为了要整体格式,还有一种就是隐藏掉的那个按钮,出来的效果没有多余空行,上面多余的空行实现用了透明色和css不可选中的样式。

react第三版(改进版):

在这里插入图片描述
代码:

/*
/*
 * @Descripttion: 
 * @version: 
 * @Author: ZhangJunQing
 * @Date: 2021-11-12 17:35:44
 * @LastEditors: ZhangJunQing
 * @LastEditTime: 2022-01-18 14:31:20
 */
import React, {
    
     Fragment } from 'react'
import {
    
     Modal, Divider, Spin } from 'antd';
import RSButton from '@com/RSButton'
import {
    
     string } from 'prop-types';
const Diff = require('diff');
export default class DiffString extends React.Component {
    
    
    static defaultProps = {
    
    
        isModalVisible: false,
        title: "预览文件差异",
        changeIsModalVisibleState: () => {
    
     },
        oldStr: "",
        newStr: "",
        contextBoxLoading: false,
    }
    /**
     * oldStr  为上次文件  已生效配置
     * 
     * newStr 为最新文件  待下发
     * 
     * contextBoxLoading  加载文件的loading
     * 
     * isModalVisible modal显示与否
     * 
     */
    state = {
    
    
        isSplitBRFlag: true,//是否为 对齐查看   这个变量目前不做动态改变  和changeisSplitBRFlagFun方法配合
        isOriginFlag: false,
        defaultAddColor: "green",
        defaultDelColor: "red",
        defaultColor: "grey"
    }
    // 源文件切换变量
    changeOriginFileFun = () => {
    
    
        this.setState({
    
    
            isOriginFlag: !this.state.isOriginFlag,

        })

    }
    // 是否为 对齐查看   
    changeisSplitBRFlagFun = () => {
    
    
        this.setState({
    
    
            isSplitBRFlag: !this.state.isSplitBRFlag
        })
    }
    /**
     * 每次进来都显示 对比文件页面
     */
    handleCancel() {
    
    
        this.setState({
    
    
            isOriginFlag: false,//默认还是显示 对比文件页面
        })
        this.props.changeIsModalVisibleState()
    }
    /**
     * 这个方法 事件委托
     * 
     * 点击p标签 改变当前p标签的样式
     * 以及更改对面等行的p标签的样式
     * 
     * 点击左边 有背景的为defaultDelColor
     * 点击右边 有背景的为defaultAddColor
     * 不是增加不是删除的的为defaultColor
     * 
     * 2px solid #fff  默认边框 
     * 如果只给当前点击的加边框 对引起整个页面抖动
     * 
     * 所有每一个p标签都添加一个边框  颜色为底色
     * 
     * 这样每次点击的时候把所有的颜色都重置
     * 
     * 然后再将点击的p换颜色 即可
     */
    changeRightLineFun = (flag, ev) => {
    
    
        let {
    
     defaultAddColor, defaultDelColor } = this.state
        let RightFileId = flag === 'right' ? document.getElementById('RightFileId') : document.getElementById('LeftFileId')
        let LeftFileId = flag === 'right' ? document.getElementById('LeftFileId') : document.getElementById('RightFileId')
        let LeftFileIdP = LeftFileId.getElementsByTagName('p')
        let RightFileIdP = RightFileId.getElementsByTagName('p')
        ev = ev || window.event;
        let target = ev.target || ev.srcElement;
        let index;
        // 点击空P标签
        if (target.style.userSelect === 'none') {
    
    
            return false;
        }
        if (target.nodeName.toLowerCase() == "p") {
    
    
            for (let i = 0; i < RightFileIdP.length; i++) {
    
    
                if (RightFileIdP[i] === target)
                    index = i;
                RightFileIdP[i].style.border = "2px solid #fff"
            }
            for (let i = 0; i < LeftFileIdP.length; i++) {
    
    
                if (LeftFileIdP[i] === target)
                    index = i;
                LeftFileIdP[i].style.border = "2px solid #fff"
            }
            if (flag === 'right') {
    
    
                if (target.parentNode.style.color === defaultAddColor) {
    
    
                    target.style.border = `2px solid ${
      
      defaultAddColor}`;
                } else {
    
    
                    target.style.border = "2px solid #000";
                }
            } else {
    
    
                if (target.parentNode.style.color === defaultDelColor) {
    
    
                    target.style.border = `2px solid ${
      
      defaultDelColor}`;
                } else {
    
    
                    target.style.border = "2px solid #000";
                }
            }

            LeftFileIdP[index].style.border = "2px solid #000";
        }

    }
    render() {
    
    
        let {
    
     isSplitBRFlag, isOriginFlag, defaultAddColor, defaultDelColor, defaultColor } = this.state
        let {
    
     title, width, isModalVisible, contextBoxLoading, oldStr, newStr, fileName, ...rest } = this.props
        // console.log(Diff.diffLines(oldStr.replace(/\r/ig, ''), newStr.replace(/\r/ig, '')), "zjqqq")
        const styleObj = {
    
    
            lineHeight: "22px",
            border: "2px solid #fff",
            paddingTop: "2px",
            paddingBottom: "2px",
            borderRadius: "4px",
            fontSize: "16px",
            paddingLeft: "10px",
            marginBottom: "0",

        }
        return (
            <Modal
                title={
    
    <div style={
    
    {
    
     display: "flex", justifyContent: "space-between" }}><span style={
    
    {
    
     fontWeight: "500" }}>{
    
    title}</span><span style={
    
    {
    
     paddingLeft: "50px" }}>{
    
    fileName ? `文件名称:${
      
      fileName}` : ""}</span><h4 style={
    
    {
    
     float: "right" }}>灰色:<span style={
    
    {
    
     color: defaultColor }}>无变化</span>;绿色:<span style={
    
    {
    
     color: defaultAddColor }}>新增</span>;红色:<span style={
    
    {
    
     color: defaultDelColor }}>删除</span></h4></div>}
                visible={
    
    isModalVisible}
                maskClosable={
    
    true}
                style={
    
    {
    
     top: "20%", minWidth: "1000px" }}
                closable={
    
    false}
                width={
    
    width}
                {
    
    ...rest}
                footer={
    
    [
                    <RSButton rsType="noIcon" key="1" title={
    
    !isOriginFlag ? "查看源文件" : "查看对比文件"} onClick={
    
    () => this.changeOriginFileFun()}></RSButton>,
                    // <RSButton rsType="noIcon" key={1} title="切换对比方式" onClick={() => this.changeisSplitBRFlagFun()}></RSButton>,
                    <RSButton rsType="noIcon" key="2" title="关闭" onClick={
    
    () => this.handleCancel()}></RSButton>
                ]}
            >
                <Spin tip="配置文件获取中..." spinning={
    
    contextBoxLoading} size="large" style={
    
    {
    
     width: "100%", height: '100%' }}>
                    {
    
    /* 绑定 key   目前这个key有两种形式 false true 字符的形式 正好对应 查看源文件和对比文件两个key  */}
                    <div style={
    
    {
    
     height: "600px", overflowY: "scroll" }} key={
    
    String(isOriginFlag)}>
                        {
    
    /* // 为了每次都处于文件顶端  */}
                        <div style={
    
    {
    
     wordBreak: "break-all", display: "flex" }} >
                            <div style={
    
    {
    
     width: "50%", paddingLeft: "20px" }} id="LeftFileId">
                                <h2 style={
    
    {
    
     fontWeight: "700" }}>已生效配置</h2>
                                {
    
    Diff.diffLines(oldStr.replace(/\r/ig, ''), isOriginFlag ? oldStr.replace(/\r/ig, '') : newStr.replace(/\r/ig, '')).map((item, index) => {
    
    
                                    return (
                                        <Fragment key={
    
    index} >
                                            <div
                                                onClick={
    
    (e) => {
    
     this.changeRightLineFun("left", e) }}
                                                style={
    
    {
    
    
                                                    fontSize: "0",
                                                    marginBottom: "0",
                                                    padding: "0",
                                                    lineHeight: "10px",
                                                    color: item.added ? defaultAddColor :
                                                        item.removed ? defaultDelColor : defaultColor,
                                                    fontWeight: item.added ? '600' :
                                                        item.removed ? '600' : '600',
                                                }}>{
    
    !item ? null : item.added ? (isSplitBRFlag ?
                                                    item.value.split('\n').map((child, idx) => {
    
    
                                                        return <Fragment key={
    
    idx} >
                                                            {
    
    child && <p style={
    
    {
    
     whiteSpace: "pre", color: "transparent", userSelect: "none", ...styleObj }} >{
    
    child}</p>}
                                                            {
    
    idx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                        </Fragment>
                                                    }) : null)
                                                    : item.value.split('\n').map((i, idx) => {
    
    
                                                        return <Fragment key={
    
    idx} >
                                                            {
    
    i && <p style={
    
    {
    
     backgroundColor: `${
      
      item.removed ? "rgb(255,227,227)" : "#fff"}`, whiteSpace: "pre", cursor: 'pointer', ...styleObj }} >{
    
    i}</p>}
                                                            {
    
    idx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                        </Fragment>
                                                    })} </div>
                                        </Fragment>
                                    )
                                })}
                            </div>
                            <Divider type="vertical" style={
    
    {
    
     width: "10px", height: "auto", minHeight: '600px' }} />
                            <div style={
    
    {
    
     flex: "1", paddingLeft: "10px", paddingRight: "10px" }} id="RightFileId" >
                                <h2 style={
    
    {
    
     fontWeight: "700" }}>待下发</h2>
                                {
    
    Diff.diffLines(isOriginFlag ? newStr.replace(/\r/ig, '') : oldStr.replace(/\r/ig, ''), newStr.replace(/\r/ig, '')).map((item, index) => {
    
    
                                    return (
                                        <Fragment key={
    
    index} >
                                            <div
                                                onClick={
    
    (e) => {
    
     this.changeRightLineFun("right", e) }}
                                                style={
    
    {
    
    
                                                    fontSize: "0",
                                                    marginBottom: "0",
                                                    padding: "0",
                                                    lineHeight: "10px",
                                                    color: item.added ? defaultAddColor :
                                                        item.removed ? defaultDelColor : defaultColor,
                                                    fontWeight: item.added ? '600' :
                                                        item.removed ? '600' : '600',
                                                }}>{
    
    !item ? null : item.removed ? (isSplitBRFlag ?
                                                    item.value.split('\n').map((child, idx) => {
    
    
                                                        return <Fragment key={
    
    idx} >
                                                            {
    
    child && <p style={
    
    {
    
     whiteSpace: "pre", color: "transparent", userSelect: "none", ...styleObj }} >{
    
    child}</p>}
                                                            {
    
    idx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                        </Fragment>
                                                    }) : null)
                                                    : item.value.split('\n').map((i, idx) => {
    
    
                                                        return <Fragment key={
    
    idx} >
                                                            {
    
    i && <p style={
    
    {
    
     backgroundColor: `${
      
      item.added ? "rgb(221,255,221)" : "#fff"}`, whiteSpace: "pre", cursor: 'pointer', ...styleObj }} key={
    
    idx}>{
    
    i}</p>}
                                                            {
    
    idx !== item.value.split('\n').length - 1 ? <br /> : null}
                                                        </Fragment>
                                                    })} </div>
                                        </Fragment>
                                    )
                                })}
                            </div>

                        </div>
                    </div>
                </Spin>
            </Modal>
        )
    }
}


加了一个点击事件,利用了事件委托,当然这里没有考虑效率问题,直接使用了事件委托写了。

总结来说diff这个npm还是很好用的,里面有很多的方法,可以按照字符比较、按照单词比较、按照行比较,但是传入的两个字符串,自己首先要先看看,不然由于后端传来的字符串的\r\n问题让我苦恼了很久,所以上面我统一过滤了\r,如果具体指导怎么用的,还是找官方文档吧。

在线测试链接:
http://tangshisanbaishou.xyz/diff/index.html

猜你喜欢

转载自blog.csdn.net/qq_43291759/article/details/122367985#comments_21823978