vue2 JS 对比两个字符串、文本内容、对象、数组差异

需要安装 deep-diff diff
npm install deep-diff
npm install diff


新建 js 脚本文本,内容如下


let observableDiff = require('deep-diff/dist/deep-diff.min').observableDiff;
let Diff = require('diff/dist/diff.min');

/**
 * 深度比较两个对象是否相同
 * @param {Object} oldData 
 * @param {Object} newData 
 */
function deepCompare(oldData, newData) {
    // 类型为基本类型时,如果相同,则返回true
    if (oldData === newData) return true;
    if (isObject(oldData) && isObject(newData) && Object.keys(oldData).length === Object.keys(newData).length) {
        // 类型为对象并且元素个数相同
        // 遍历所有对象中所有属性,判断元素是否相同
        for (const key in oldData) {
            if (oldData.hasOwnProperty(key)) {
                if (!deepCompare(oldData[key], newData[key]))
                    // 对象中具有不相同属性 返回false
                    return false;
            }
        }
    } else if (isArray(oldData) && isArray(oldData) && oldData.length === newData.length) {
        // 类型为数组并且数组长度相同
        for (let i = 0, length = oldData.length; i < length; i++) {
            if (!deepCompare(oldData[i], newData[i]))
                // 如果数组元素中具有不相同元素,返回false
                return false;
        }
    } else {
        // 其它类型,均返回false
        return false;
    }
    // 走到这里,说明数组或者对象中所有元素都相同,返回true
    return true;
}



function judgeType(change) {
    if (arguments.length == 0) {
        return ''; //无参数传入
    }
    if (change === null) {
        return 'null'
    }
    if (change === undefined && arguments.length > 0) {
        return 'undefined'
    }
    if (change instanceof Function) {
        return 'function'
    }
    if (Object.prototype.toString.call(change) == "[object Object]") {
        return 'object'
    }
    if (change instanceof Array) {
        return 'arry'
    }
    if (change instanceof Number || typeof change == 'number') {
        return 'number'
    }
    if (change instanceof String || typeof change == 'string') {
        return 'string'
    }
    if (change instanceof Boolean || typeof change == 'boolean') {
        return 'boolean'
    }
}
/***
 * isSamePath 比较是否有删除项
 * */
function isSamePath(diff, path) {
    let D = diff['D'] || [];
    let tmp = null;
    for (let i = 0; i < D.length; i++) {
        tmp = D[i].path; //
        if (deepCompare(tmp, path)) {
            return true
        }
    }
    return false;
}

function turnArrToTable(arr) {
    let thead = null;
    let tr = arr.map(item => {
        // console.log(item);
        let td = [];
        let th = [];
        for (let k in item) {
            if (!thead) {
                th.push(`<th>${k}</th>`)
            }
            td.push(`<td>${item[k]}</td>`)
        }
        if (!thead) {
            thead = `<tr>${th.join('')}</tr>`;
        }
        return `<tr>${td.join('')}</tr>`
    });
    let table = `<table><thead>${thead}</thead><tbody>${tr.join('')}</tbody></table>`;
    return table;
}

function getCompareValue(tree, path) {
    let res = tree;
    for (let val of path) {
        res = res ? res[val] : '';
    }
    return res;
}

export function toForm(obj, compare) {
    let diff = null;
    if (compare) {
        diff = delRow(obj, compare);
    }

    function getRichText(obj, path = [], tree = 1) {
        let str = '';
        if (judgeType(obj) == 'object') {
            console.log(obj,'22222')
            for (let k in obj) {
                let nextPath = [...path, k];
                if (judgeType(obj[k]) == 'object' || (judgeType(obj[k]) == 'arry' && judgeType(obj[k][0])=='object')) { //
                    str += `<div class='form-${tree} ${isSamePath(diff, nextPath) ? "delRow" : ""}'>
                        <p class='form-title form-title-${tree}'>${k}</p>
                        <div class='form-body form-body-${tree}'>${getRichText(obj[k], nextPath, tree + 1)}</div>
                    </div>`
                } else {
                    str += `<div class='form-${tree} ${isSamePath(diff, nextPath) ? "delRow flex" : "flex"}'>
                        <p class=' form-label form-label-${tree}'>${k}:</p>
                        <div class='form-value form-value-${tree}'>${getRichText(obj[k], nextPath, tree + 1)}</div>
                    </div>`
                }
            }
        } else if (judgeType(obj) == 'arry') {
            // for (let i = 0; i < obj.length; i++) {
            //     toForm(obj[i])
            // }
            if(judgeType(obj[0]) !== 'object') {
                return getRichText(obj.join('、'))
            } else {
                return turnArrToTable(obj)
            }
            
        } else {
            let tmp = getCompareValue(compare, path);
            return editStr(obj, tmp)
        }
        return str
    }
    return getRichText(obj)
}


export function delRow(obj1, obj2) {
    let diff = {};
    observableDiff(obj1, obj2, function (d) {
        diff[d.kind] = diff[d.kind] || [];
        diff[d.kind].push(d)
    });
    return diff;
}

export function editStr(str1, str2) {
    if (str1 && str2) {
        let str = '';
        const diff = Diff.diffChars(str1 + '', str2 + '');
        diff.forEach((part) => {
            switch (part.added ? 'add' : part.removed ? 'del' : 'same') {
                case 'del':
                    str += `<span class='del'>${part.value}</span>`
                    break;
                case 'same':
                    str += `<span class='same'>${part.value}</span>`
                    break;
            }
        });
        return str
    }
    return str1
}

使用

引入上方定义的脚本文件

import {toForm} from '脚本文件路径'


定义方法
 
change(before, after) {
      this.form1 = toForm(before, after);
      this.form2 = toForm(after, before);
}

使用方法

this.change("需要比对的内容11111", "需要比对的内容222");


文本显示内容

<div class='before' v-html='form1'>
    
</div>


<div class='after' v-html='form2'>

</div>

css设置
.before .del{
    color:red;
}
.after .del{
    color:blue;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值