diff 订阅
diff 命令比较文本文件。它能比较单个文件或者目录内容。diff 命令只有当输入为文本文件时才有效。如果指定了 Directory1 和 Directory2 参数,diff 命令比较两个目录下名字相同的文本文件。列出不同的二进制文件、公共子目录和只在一个目录出现的文件。diff命令用于比较两个文件的差异,它可以被制作成补丁文件,使用patch命令对相应的文件打补丁。 展开全文
diff 命令比较文本文件。它能比较单个文件或者目录内容。diff 命令只有当输入为文本文件时才有效。如果指定了 Directory1 和 Directory2 参数,diff 命令比较两个目录下名字相同的文本文件。列出不同的二进制文件、公共子目录和只在一个目录出现的文件。diff命令用于比较两个文件的差异,它可以被制作成补丁文件,使用patch命令对相应的文件打补丁。
信息
描    述
diff 命令比较文本文件
用途语法
比较两个文件的内容
标    志
将每行末尾当作单个新行标记处理
diff 命令
只有当输入为文本文件时才有效
外文名
diff
diffLinux
比较文本文件。语法比较两个文件的内容diff [ -c | -C Lines | -D [ String ] | -e | -f | -n ] [ -b ] [ -i] [ -t ] File 1 File2diff [ -h ] [ -b ] File 1 File2排序字典的内容并比较不同的文件diff [ -c | -C Lines | -e | -f | -n ] [ -b ] [ -i ] [ -l ] [ -r ] [ -s ] [ -S File ] [ -t ] [ -w ] Directory1 Directory2diff [ -h ] [ -b ] Directory1 Directory2diff 命令比较文本文件。它能比较单个文件或者目录内容。注:diff 命令只有当输入为文本文件时才有效。如果指定了 Directory1 和 Directory2 参数,diff 命令比较两个目录下名字相同的文本文件。列出不同的二进制文件、公共子目录和只在一个目录出现的文件。当 diff 命令运行于常规文件时,且当目录比较期间比较不同的文本文件时,diff 命令显示文件中哪些行必须更改以保持它们一致。如果 File1 和 File2 参数都不是目录,其中之一可能给定负号“-”,以采用标准输入。如果 File1 参数是目录,则使用目录中与 File2 参数指定的文件名一致的那个文件。Lines Affected in File1 Action Lines Affected in File2Number1 a Number2[,Number3]Number1[,Number2] d Number3Number1[,Number2] c Number3[,Number4]这些行类似于 ed 子命令将 File1 文件转换成 File2 文件。Action 字母之前的数字指 File1;后面的数字则指 File2。因此,通过将 a 替换成 d,从右往左读,您就能知道如何将 File2 转换成 File1。在 ed 命令下,相同的对(即 Number1 = Number2)会简略为单个数字。下列每一行,diff 命令显示以 <:(小于符号,冒号)开始的第一个文件中的所有受影响行,然后显示以 >(大于符号)开始的第二个文件中的所有受影响行。退出值 0 表示没有不同,1 表示找到不同处,2 表示出错。注:如果指定了多于一个的 -c、-C、-D、-e、-f 或者 -n 标志,命令行上的最后一个具有优先权。系统不发出错误消息。-b 将每行末尾当作单个新行标记处理(忽略新行字符前的空格字符)的任意数量空格字符与其他空格字符串(除了新行标记)同样地比较。-C Lines 启动 diff 命令,但只比较 Lines 变量指定的行数。-C 标志稍微修改输出。输出以文件的相同部分和创建日期开始。每个更改以 12 个 *(星号)组成的行分隔。从 File1 中要删的行以 -(减号)标记,File2 中要添加的行以 +(加号)标记。从一个文件更改到另一个文件的行在两个文件中都以 !(惊叹号)标记。在每一个文件的指定上下文行中的更改会被整组一起输出。-c 启动 diff 命令,比较三行上下文。-c 标志稍微修改输出。输出以涉及文件的标识和它们的创建日期开始。每个更改以 12 个 *(星号)组成的行分隔。File1 中要删的行以 -(减号)标记,要被添加到 File2 的行以 + (加号)标记。从一个文件更改到另一个文件的行在两个文件中都以 !(惊叹号)标记。在每一个文件的指定上下文行中的更改会被整组一起输出。-D [ String ] 使得 diff 命令在标准输出上建立一个 File1 和 File2 的合并版本。包含了 C 预处理器控件以便没有定义 String 的结果编译等同于编译 File1,同时定义 String 产生 File2。-e 以适合 ed 编辑器的格式进行输出,将 File1 转换成 File2。当使用这个标志时,以下 shell 程序可以帮助维护一个文件的多个版本。手头仅需要由 diff 命令生成的一个祖先文件($1)和一系列版本的 ed 脚本($2、$3、...)。标准输出上的最近版本如下:(shift; cat $*; echo '1,$p') | ed - $1当使用 -e 标志比较目录时,输出上添加了额外的命令,因此,结果是一个 shell 脚本,将两个目录上的共有文本文件从 Directory1 上的状态转换到 Directory2 上的状态。注:由 -e 或 -f 标志产生的编辑脚本无法创建由单个组成的行。(周期)。-f 以不适合 ed 编辑器的格式创建输出,按照在 -e 标志下产生的逆向顺序显示从 File1 到 File2 的转换的必要修改。-h 如果要更改的部分比较短而且分隔清晰,则执行备用的比较可能会更快。-h 标志可用于任意长度的文件。-c、-C、-D、-e、-f 和 -n 标志无法与 -h 标志一起使用。当使用 -h 标志时,除了 -b 标志,其他标志一律忽略。-i 忽略字母大小写。例如,小写 a 被认为同大写 A 一样。-l 长输出格式。每个由文本文件比较 diff 命令获得的结果通过命令 pr 输送分页。在报告所有文本文件不同之处后,其他不同之处将被记忆和总结。-n 产生类似于 -e 标志创建的输出,但是顺序相反,而且在每一插入或删除命令上进行更改计数。这是修订控件系统(RCS)所用的格式。-r 使 diff 命令的应用程序递归到遇到的公共子目录。-s 报告相同的文件,否则不提。-S [ File ] 当比较目录时,忽略在 File 变量指定的文件之前整理名称的文件。-S 标志只用于 Directory1 和 Directory2 参数指定的目录。如果您将 -r 标志与 -S 标志一起使用, -S 标志在 Directory1 和 Directory2 子目录中不进行递归。-t 在输出行扩展制表符。典型输出或者 -c 标志输出会添加字符到每一行首,这会影响初始行的缩进,使得输出列表难以解释。该标志则保留原始源的缩进。-w 忽略所有空格和制表符,将所有其他空白字符串视为一致。例如,if ( a == b ) 与 if(a==b) 相等。退出状态此命令返回下列退出值:0 未找到不同处。1 找到不同处。>1 发生错误。1. 要比较两个文件,请输入:diff chap1.back chap1只显示文件 chap1.bak 和 chap1 的不同之处。2. 要比较两个文件,但是忽略空格字符个数的区别,请输入:diff -w prog.c.bak prog.c如果两行仅仅空格和制表符数目不同,则 diff -w 目录认为它们相等。3. 要创建一个包含 ed 命令可以用于从另一个文件重构文件的命令的文件,请输入:diff -e chap2 chap2.old >new.to.old.ed这将创建一个名为 new.to.old.ed 的文件,它包含 ed 子命令,把 chap2 转换回在 chap2.old 中找到的文本版本。在大多数情况下,new.to.old.ed 比 chap2.old 要小很多。您可以通过删除 chap2.old 以节省磁盘空间,您也可以在任何时候重建它,通过输入:(cat new.to.old.ed ; echo '1,$p') | ed - chap2 >chap2.old括号中的命令把 1,$p 添加到编辑命令的末尾,发送给 ed 编辑器。1,$p 使得 ed 命令在编辑完成后将文件写到标准输出。这一修改的命令序列然后从管道传给 ed 命令(| ed),编辑器读取它作为标准输入。- 标志使 ed 命令不显示文件大小以及其他附加信息因为它们易与 chap2.old 的文本混肴。文件/usr/bin/diff 包含 diff 命令。
收起全文
精华内容
下载资源
问答
  • diff

    2019-07-29 11:32:39
    diff是Unix系统的一个很重要的工具程序。 它用来比较两个文本文件的差异,是代码版本管理的基石之一。你在命令行下,输入: $ diff <变动前的文件> <变动后的文件> diff就会告诉你,这两个文件有何差异...

    diff是Unix系统的一个很重要的工具程序。

    它用来比较两个文本文件的差异,是代码版本管理的基石之一。你在命令行下,输入:

    $ diff <变动前的文件> <变动后的文件>
    

    diff就会告诉你,这两个文件有何差异。它的显示结果不太好懂,下面我就来说明,如何读懂diff。

    一、diff的三种格式

    由于历史原因,diff有三种格式:

     * 正常格式(normal diff)
    
      * 上下文格式(context diff)
    
      * 合并格式(unified diff)
    

    我们依次来看。

    二、示例文件

    为了便于讲解,先新建两个示例文件。

    第一个文件叫做f1,内容是每行一个a,一共7行。

       a
      a
      a
      a
      a
      a
      a
    

    第二个文件叫做f2,修改f1而成,第4行变成b,其他不变。

       a
      a
      a
      b
      a
      a
      a
    

    三、正常格式的diff

    现在对f1和f2进行比较:

     $ diff f1 f2
    

    这时,diff就会显示正常格式的结果:

      4c4
      < a
      ---
      > b
    

    第一行是一个提示,用来说明变动位置。

      4c4
    

    它分成三个部分:前面的"4",表示f1的第4行有变化;中间的"c"表示变动的模式是内容改变(change),其他模式还有"增加"(a,代表addition)和"删除"(d,代表deletion);后面的"4",表示变动后变成f2的第4行。

    第二行分成两个部分。

     < a
    

    前面的小于号,表示要从f1当中去除该行(也就是第4行),后面的"a"表示该行的内容。

    第三行用来分割f1和f2。

      ---
    

    第四行,类似于第二行。

    > b
    

    前面的大于号表示f2增加了该行,后面的"b"表示该行的内容。

    最早的Unix(即AT&T版本的Unix),使用的就是这种格式的diff。

    四、上下文格式的diff

    上个世纪80年代初,加州大学伯克利分校推出BSD版本的Unix时,觉得diff的显示结果太简单,最好加入上下文,便于了解发生的变动。因此,推出了上下文格式的diff。

    它的使用方法是加入c参数(代表context)。

     $ diff -c f1 f2
    

    显示结果如下:

     *** f1	2012-08-29 16:45:41.000000000 +0800
      --- f2	2012-08-29 16:45:51.000000000 +0800
      ***************
      *** 1,7 ****
       a
       a
       a
      !a
       a
       a
       a
      --- 1,7 ----
       a
       a
       a
      !b
       a
       a
       a
    

    这个结果分成四个部分。

    第一部分的两行,显示两个文件的基本情况:文件名和时间信息。

      *** f1	2012-08-29 16:45:41.000000000 +0800
      --- f2	2012-08-29 16:45:51.000000000 +0800
    

    "***“表示变动前的文件,”—"表示变动后的文件。

    第二部分是15个星号,将文件的基本情况与变动内容分割开。

    ***************
    

    第三部分显示变动前的文件,即f1。

     *** 1,7 ****
       a
       a
       a
      !a
       a
       a
       a
    

    这时不仅显示发生变化的第4行,还显示第4行的前面三行和后面三行,因此一共显示7行。所以,前面的"*** 1,7 ****"就表示,从第1行开始连续7行。

    另外,文件内容的每一行最前面,还有一个标记位。如果为空,表示该行无变化;如果是感叹号(!),表示该行有改动;如果是减号(-),表示该行被删除;如果是加号(+),表示该行为新增。

    第四部分显示变动后的文件,即f2。

      --- 1,7 ----
       a
       a
       a
      !b
       a
       a
       a
    

    除了变动行(第4行)以外,也是上下文各显示三行,总共显示7行。

    五、合并格式的diff

    如果两个文件相似度很高,那么上下文格式的diff,将显示大量重复的内容,很浪费空间。1990年,GNU diff率先推出了"合并格式"的diff,将f1和f2的上下文合并在一起显示。

    它的使用方法是加入u参数(代表unified)。

      $ diff -u f1 f2
    

    显示结果如下:

      --- f1	2012-08-29 16:45:41.000000000 +0800
      +++ f2	2012-08-29 16:45:51.000000000 +0800
      @@ -1,7 +1,7 @@
       a
       a
       a
      -a
      +b
       a
       a
       a
    

    它的第一部分,也是文件的基本信息。

      --- f1	2012-08-29 16:45:41.000000000 +0800
      +++ f2	2012-08-29 16:45:51.000000000 +0800
    

    "—“表示变动前的文件,”+++"表示变动后的文件。

    第二部分,变动的位置用两个@作为起首和结束。

      @@ -1,7 +1,7 @@
    

    前面的"-1,7"分成三个部分:减号表示第一个文件(即f1),"1"表示第1行,“7"表示连续7行。合在一起,就表示下面是第一个文件从第1行开始的连续7行。同样的,”+1,7"表示变动后,成为第二个文件从第1行开始的连续7行。

    第三部分是变动的具体内容。

        a
       a
       a
      -a
      +b
       a
       a
       a
    

    除了有变动的那些行以外,也是上下文各显示3行。它将两个文件的上下文,合并显示在一起,所以叫做"合并格式"。每一行最前面的标志位,空表示无变动,减号表示第一个文件删除的行,加号表示第二个文件新增的行。

    六、git格式的diff

    版本管理系统git,使用的是合并格式diff的变体。

      $ git diff
    

    显示结果如下:

     diff --git a/f1 b/f1
      index 6f8a38c..449b072 100644
      --- a/f1
      +++ b/f1
      @@ -1,7 +1,7 @@
       a
       a
       a
      -a
      +b
       a
       a
       a
    

    第一行表示结果为git格式的diff。

     diff --git a/f1 b/f1
    

    进行比较的是,a版本的f1(即变动前)和b版本的f1(即变动后)。

    第二行表示两个版本的git哈希值(index区域的6f8a38c对象,与工作目录区域的449b072对象进行比较),最后的六位数字是对象的模式(普通文件,644权限)。

      index 6f8a38c..449b072 100644
    

    第三行表示进行比较的两个文件。

     --- a/f1
      +++ b/f1
    

    "—“表示变动前的版本,”+++"表示变动后的版本。

    后面的行都与官方的合并格式diff相同。

     @@ -1,7 +1,7 @@
       a
       a
       a
      -a
      +b
       a
       a
       a
    

    七、阅读材料

    * diff - Wikipedia

    * How to read a patch or diff

    * How to work with diff representation in git

    (完)

    展开全文
  • Diff

    2016-05-05 23:29:03
    1 "git diff" 与暂存区相比,对未存档的文件做哪些修改; 2 --staged, HEAD 2.1 已存档的文件,查看暂存区和最近提交的历史文件的区别 "git diff --stages" 2.2 查看文件修改与最新提交的历史文件的区别 "git ...

    1 "git diff"

    与暂存区相比,对未存档的文件做哪些修改;

    2 --staged, HEAD

    2.1 已存档的文件,查看暂存区和最近提交的历史文件的区别

    "git diff --stages"

    2.2 查看文件修改与最新提交的历史文件的区别

    "git diff HEAD"

    其中,HEAD表示最后一次提交的别名;HEAD^表示前一次提交的别名;HEAD~n标识前n次提交的别名;

    3 --color-words, --word-diff

    针对长行小改动,使用如下命令查看区别

    "git diff --color-words"

    "git diff --word-diff"

    4 --stat

    "git diff-stat" 只查看哪个文件修改


    展开全文
  • diff参数

    万次阅读 2020-08-24 14:36:40
    diff(选项)(参数) 选项 -<行数>:指定要显示多少行的文本。此参数必须与-c或-u参数一并使用; -a或——text:diff预设只会逐行比较文本文件; -b或--ignore-space-change:不检查空格字符的不同; -B或--...

    语法
    diff(选项)(参数)
    选项
    -<行数>:指定要显示多少行的文本。此参数必须与-c或-u参数一并使用;
    -a或——text:diff预设只会逐行比较文本文件;
    -b或--ignore-space-change:不检查空格字符的不同;
    -B或--ignore-blank-lines:不检查空白行;
    -c:显示全部内容,并标出不同之处;
    -C<行数>或--context<行数>:与执行“-c-<行数>”指令相同;
    -d或——minimal:使用不同的演算法,以小的单位来做比较;
    -D<巨集名称>或ifdef<巨集名称>:此参数的输出格式可用于前置处理器巨集;
    -e或——ed:此参数的输出格式可用于ed的script文件;
    -f或-forward-ed:输出的格式类似ed的script文件,但按照原来文件的顺序来显示不同处;
    -H或--speed-large-files:比较大文件时,可加快速度;
    -l<字符或字符串>或--ignore-matching-lines<字符或字符串>:若两个文件在某几行有所不同,而之际航同时都包含了选项中指定的字符或字符串,则不显示这两个文件的差异;
    -i或--ignore-case:不检查大小写的不同;
    -l或——paginate:将结果交由pr程序来分页;
    -n或——rcs:将比较结果以RCS的格式来显示;
    -N或--new-file:在比较目录时,若文件A仅出现在某个目录中,预设会显示:Only in目录,文件A 若使用-N参数,则diff会将文件A 与一个空白的文件比较;
    -p:若比较的文件为C语言的程序码文件时,显示差异所在的函数名称;
    -P或--unidirectional-new-file:与-N类似,但只有当第二个目录包含了第一个目录所没有的文件时,才会将这个文件与空白的文件做比较;
    -q或--brief:仅显示有无差异,不显示详细的信息;
    -r或——recursive:比较子目录中的文件;
    -s或--report-identical-files:若没有发现任何差异,仍然显示信息;
    -S<文件>或--starting-file<文件>:在比较目录时,从指定的文件开始比较;
    -t或--expand-tabs:在输出时,将tab字符展开;
    -T或--initial-tab:在每行前面加上tab字符以便对齐;
    -u,-U<列数>或--unified=<列数>:以合并的方式来显示文件内容的不同;
    -v或——version:显示版本信息;
    -w或--ignore-all-space:忽略全部的空格字符;
    -W<宽度>或--width<宽度>:在使用-y参数时,指定栏宽;
    -x<文件名或目录>或--exclude<文件名或目录>:不比较选项中所指定的文件或目录;
    -X<文件>或--exclude-from<文件>;您可以将文件或目录类型存成文本文件,然后在=<文件>中指定此文本文件;
    -y或--side-by-side:以并列的方式显示文件的异同之处;
    --help:显示帮助;
    --left-column:在使用-y参数时,若两个文件某一行内容相同,则仅在左侧的栏位显示该行内容;
    --suppress-common-lines:在使用-y参数时,仅显示不同之处。
    还有个colordiff命令,用颜色标识不同的地方。需要先安装

    展开全文
  • Diff算法

    万次阅读 2019-06-12 08:38:53
    Diff算法 什么是Diff算法? diff算法作为Virtual DOM的加速器,其算法的改进优化是React整个界面渲染的基础和性能的保障,同时也是React源码中最神秘的,最不可思议的部分 传统Diff: 计算一棵树形结构转换为另一棵...

    Diff算法

    什么是Diff算法?

    diff算法作为Virtual DOM的加速器,其算法的改进优化是React整个界面渲染的基础和性能的保障,同时也是React源码中最神秘的,最不可思议的部分

    传统Diff:

    计算一棵树形结构转换为另一棵树形结构需要最少步骤,如果使用传统的diff算法通过循环递归遍历节点进行对比,其复杂度要达到O(n^3),其中n是节点总数,效率十分低下,假设我们要展示1000个节点,那么我们就要依次执行上十亿次的比较。

    下面附上一则简单的传统diff算法:

    let result = [];
    // 比较叶子节点
    const diffLeafs = function (beforeLeaf, afterLeaf) {
        // 获取较大节点树的长度
        let count = Math.max(beforeLeaf.children.length, afterLeaf.children.length);
        // 循环遍历
        for (let i = 0; i < count; i++) {
            const beforeTag = beforeLeaf.children[i];
            const afterTag = afterLeaf.children[i];
            // 添加 afterTag 节点
            if (beforeTag === undefined) {
                result.push({ type: "add", element: afterTag });
                // 删除 beforeTag 节点
            } else if (afterTag === undefined) {
                result.push({ type: "remove", element: beforeTag });
                // 节点名改变时,删除 beforeTag 节点,添加 afterTag 节点
            } else if (beforeTag.tagName !== afterTag.tagName) {
                result.push({ type: "remove", element: beforeTag });
                result.push({ type: "add", element: afterTag });
                // 节点不变而内容改变时,改变节点
            } else if (beforeTag.innerHTML !== afterTag.innerHTML) {
                if (beforeTag.children.length === 0) {
                    result.push({
                        type: "changed",
                        beforeElement: beforeTag,
                        afterElement: afterTag,
                        html: afterTag.innerHTML
                    });
                } else {
                    // 递归比较
                    diffLeafs(beforeTag, afterTag);
                }
            }
        }
        return result;
    }
    

    React Diff算法优化策略图

    在这里插入图片描述

    • React更新阶段会对ReactElement类型判断而进行不同的操作;ReactElement类型包含三种即:文本、Dom、组件;
    • 每个类型的元素更新处理方式:
      • 自定义元素的更新,主要是更新render出的节点,做甩手掌柜交给render出的节点的对应component去管理更新。
      • text节点的更新很简单,直接更新文案。
      • 浏览器基本元素的更新,分为两块:
        • 更新属性,对比出前后属性的不同,局部更新。并且处理特殊属性,比如事件绑定。
        • 子节点的更新,子节点更新主要是找出差异对象,找差异对象的时候也会使用上面的shouldUpdateReactComponent来判断,如果是可以直接更新的就会递归调用子节点的更新,这样也会递归查找差异对象。不可直接更新的删除之前的对象或添加新的对象。之后根据差异对象操作dom元素(位置变动,删除,添加等)

    React中Diff算法的实现

    React Diff:

    之前说过,React采用虚拟DOM技术实现对真实DOM的映射,即React Diff算法的差异查找实质是对两个JavaScript对象的差异查找;

    基于三个策略:

    1.Web UI中DOM节点跨层级的移动操作特别少,可以忽略不计。(tree diff)
    2.拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结。(component diff)
    3.对于同一层级的一组子节点,它们可以通过唯一ID进行区分。(element diff)
    
    对于以上三个策略,react分别对tree diff,component diff,element diff进行算法优化。
    1.tree diff

    基于策略一,WebUI中DOM节点跨层级的移动操作少的可以忽略不计,React对Virtual DOM树进行层级控制,只会对相同层级的DOM节点进行比较,即同一个父元素下的所有子节点,当发现节点已经不存在了,则会删除掉该节点下所有的子节点,不会再进行比较。这样只需要对DOM树进行一次遍历,就可以完成整个树的比较。复杂度变为O(n);

    疑问:当我们的DOM节点进行跨层级操作时,diff会有怎么样的表现呢?

    如下图所示,A节点及其子节点被整个移动到D节点下面去,由于React只会简单的考虑同级节点的位置变换,而对于不同层级的节点,只有创建和删除操作,所以当根节点发现A节点消失了,就会删除A节点及其子节点,当D发现多了一个子节点A,就会创建新的A作为其子节点。
    此时,diff的执行情况是:

    createA-->createB-->createC-->deleteA

    在这里插入图片描述

    Tree DIFF是对树的每一层进行遍历,如果某组件不存在了,则会直接销毁。如图所示,左边是旧属,右边是新属,第一层是R组件,一模一样,不会发生变化;第二层进入Component DIFF,同一类型组件继续比较下去,发现A组件没有,所以直接删掉A、B、C组件;继续第三层,重新创建A、B、C组件。

    由此可以发现,当出现节点跨层级移动时,并不会出现想象中的移动操作,而是会进行删除,重新创建的动作,这是一种很影响React性能的操作。因此官方也不建议进行DOM节点跨层级的操作。

    2.componnet diff

    React是基于组件构建应用的,对于组件间的比较所采用的策略也是非常简洁和高效的。

    • 如果是同一个类型的组件,则按照原策略进行Virtual DOM比较。

    • 如果不是同一类型的组件,则将其判断为dirty component,从而替换整个组价下的所有子节点。

    • 如果是同一个类型的组件,有可能经过一轮Virtual DOM比较下来,并没有发生变化。如果我们能够提前确切知道这一点,那么就可以省下大量的diff运算时间。因此,React允许用户通过shouldComponentUpdate()来判断该组件是否需要进行diff算法分析。

    如下图所示,当组件D变为组件G时,即使这两个组件结构相似,一旦React判断D和G是不用类型的组件,就不会比较两者的结构,而是直接删除组件D,重新创建组件G及其子节点。虽然当两个组件是不同类型但结构相似时,进行diff算法分析会影响性能,但是毕竟不同类型的组件存在相似DOM树的情况在实际开发过程中很少出现,因此这种极端因素很难在实际开发过程中造成重大影响。

    在这里插入图片描述

    3.element diff

    当节点属于同一层级时,diff提供了3种节点操作,分别为INSERT_MARKUP(插入),MOVE_EXISTING(移动),REMOVE_NODE(删除)。

    • INSERT_MARKUP:新的组件类型不在旧集合中,即全新的节点,需要对新节点进行插入操作。
    • MOVE_EXISTING:旧集合中有新组件类型,且element是可更新的类型,这时候就需要做移动操作,可以复用以前的DOM节点。
    • REMOVE_NODE:旧组件类型,在新集合里也有,但对应的element不同则不能直接复用和更新,需要执行删除操作,或者旧组件不在新集合里的,也需要执行删除操作。

    在这里插入图片描述

    Element DIFF紧接着以上统一类型组件继续比较下去,常见类型就是列表。同一个列表由旧变新有三种行为,插入、移动和删除,它的比较策略是对于每一个列表指定key,先将所有列表遍历一遍,确定要新增和删除的,再确定需要移动的。如图所示,第一步将D删掉,第二步增加E,再次执行时A和B只需要移动位置即可。

    React中Diff算法实现的代码

    _updateChildren: function(nextNestedChildrenElements, transaction, context) {
        var prevChildren = this._renderedChildren;
        var removedNodes = {};
        var mountImages = [];
        // 获取新的子元素数组
        var nextChildren = this._reconcilerUpdateChildren(
          prevChildren,
          nextNestedChildrenElements,
          mountImages,
          removedNodes,
          transaction,
          context
        );
        if (!nextChildren && !prevChildren) {
          return;
        }
        var updates = null;
        var name;
        var nextIndex = 0;
        var lastIndex = 0;
        var nextMountIndex = 0;
        var lastPlacedNode = null;
        for (name in nextChildren) {
          if (!nextChildren.hasOwnProperty(name)) {
            continue;
          }
          var prevChild = prevChildren && prevChildren[name];
          var nextChild = nextChildren[name];
          if (prevChild === nextChild) {
            // 同一个引用,说明是使用的同一个component,所以我们需要做移动的操作
            // 移动已有的子节点
            // NOTICE:这里根据nextIndex, lastIndex决定是否移动
            updates = enqueue(
              updates,
              this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex)
            );
            // 更新lastIndex
            lastIndex = Math.max(prevChild._mountIndex, lastIndex);
            // 更新component的.mountIndex属性
            prevChild._mountIndex = nextIndex;
          } else {
            if (prevChild) {
              // 更新lastIndex
              lastIndex = Math.max(prevChild._mountIndex, lastIndex);
            }
    
            // 添加新的子节点在指定的位置上
            updates = enqueue(
              updates,
              this._mountChildAtIndex(
                nextChild,
                mountImages[nextMountIndex],
                lastPlacedNode,
                nextIndex,
                transaction,
                context
              )
            );
            nextMountIndex++;
          }
          // 更新nextIndex
          nextIndex++;
          lastPlacedNode = ReactReconciler.getHostNode(nextChild);
        }
        // 移除掉不存在的旧子节点,和旧子节点和新子节点不同的旧子节点
        for (name in removedNodes) {
          if (removedNodes.hasOwnProperty(name)) {
            updates = enqueue(
              updates,
              this._unmountChild(prevChildren[name], removedNodes[name])
            );
          }
        }
      }
    

    基于中Diff的开发建议

    基于tree diff:

    • 开发组件时,注意保持DOM结构的稳定;即,尽可能少地动态操作DOM结构,尤其是移动操作。
    • 当节点数过大或者页面更新次数过多时,页面卡顿的现象会比较明显。
    • 这时可以通过 CSS 隐藏或显示节点,而不是真的移除或添加 DOM 节点。

    基于component diff:

    • 注意使用 shouldComponentUpdate() 来减少组件不必要的更新。
    • 对于类似的结构应该尽量封装成组件,既减少代码量,又能减少component diff的性能消耗。

    基于element diff:

    • 对于列表结构,尽量减少类似将最后一个节点移动到列表首部的操作,当节点数量过大或更新操作过于频繁时,在一定程度上会影响 React 的渲染性能。
    展开全文
  • diff算法

    2020-11-23 16:04:31
    1.tree diff2.componnet diff3.element diff基于中Diff的开发建议基于tree diff基于component diff基于element diff 一直都没有好好的看一下diff算法 今天搞一下 什么是Diff算法? diff算法作为Virt
  • excel diff

    2015-03-17 22:06:51
    能够diff excel,实现svn diff的功能,作为插件使用
  • 对比git diff命令之前,我们先新建一个test.txt文本,先后执行如下命令 # 第一次编辑文本,新增第一行内容 first content. # 执行git命令-提交到版本库 $ git add test.txt $ git commit -m "first submit" # 第二次...
  • diff diff3 命令

    2017-10-30 13:43:39
    diff 命令在最简单的情况下,比较给定的两个文件的不同.如果使用'-'代替'文件'参数,则要比较的内容将来自标准输入.diff 命令是以逐行的方式,比较文本文件的异同处.如果该命令指定进行目录的比较,则将会...
  • git diff/difftool

    2019-07-30 20:27:00
    参考好文:使用命令和P4Merge...git difftool 即可弹出比较工具的界面 哈哈 =========================== 本地区域 git diff/difftool filepath 不带任何命令参数,工作区(本地文件)与暂存区比较,后面不带...
  • Git diff

    千次阅读 2020-02-18 19:41:27
    git diff显示提交,提交和工作树等之间的变化 此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。 常用命令: 比较版本库中任意两个分支的差异。 git diff <...
  • svn diff

    2020-08-06 07:31:00
    svn diff 文件名 svn diff 文件名 会查看本地版本库中所作的修改。 cd 到文件所属的目录下使用 svn diff 文件名 svn diff xx.cs 或者直接 svn diff 文件路径/文件名 svn diff xxx/xxx/xx.cs svn diff -r r...
  • git diff的最全最详细的4大主流用法

    万次阅读 多人点赞 2019-03-25 16:40:02
    1.git diff用来比较文件之间的不同,其基本用法如下: (1)git diff:当工作区有改动,临时区为空,diff的对比是“工作区与最后一次commit提交的仓库的共同文件”;当工作区有改动,临时区不为空,diff对比的是...
  • git diff

    2019-10-01 17:01:32
    git diff 显示工作目录与索引区文件之间的差异git diff --cached显示索引区与git仓库之间的差异git diff HEAD 显示工作目录与git仓库之间的差异 git diff HEAD^ 比较上次提交 git diff HEAD~2 比较上2次提交--diff-...
  • java-diff-utils 状态 介绍 Diff Utils库是一个开放源代码库,用于执行文本之间的比较操作:计算差异,应用补丁,生成统一的差异或对其进行解析,生成差异输出以方便将来显示(如并排视图)等等。 构建该库的主要...
  • diff git_git diff长行

    2020-07-27 18:38:08
    diff gitI find git diff output is not easy to read when the text file contains long lines that is long enough to exceeds the screen size. 我发现当文本文件包含的行足够长以超过屏幕尺寸时, git diff输出...
  • 每个开发者多少都接触过git的diff功能,如下图: 该功能能够展示出某个文件的改动信息,非常便于开发者的日常开发。 本文将探讨下此功能实现的原理。 myers diff 做了啥 引用个例子 a = ABCABBA b = CBABAC 现在...
  • Linux diff

    2019-04-30 11:45:58
    git diff 格式 git diff commitA commitB 可以是commit的hash值 也可使HEAD,HEAD~3等 git diff branch1 branch2 比较不同分支差异 git diff fileName 比较暂存区和工作区 只有通过 git add 跟踪过的文件...
  • diff命令

    2020-07-17 21:29:22
    diff命令 diff命令能够比较给定的两个文件的不同,如果使用-代替文件参数,则要比较的内容将来自标准输入,diff命令是以逐行的方式比较文本文件的异同处,如果该命令指定进行目录的比较,则将会比较该目录中具有相同...
  • yapf_diff 仅更改已更改的内容 安装 与pipenv pipenv install git+https://github.com/luxresearch/yapf-diff.git@master#egg=yapf-diff 带点pip install git+...
  • mysqldiff

    2019-08-08 21:01:43
    本文介绍mysqldiff工具来比较数据表结构,并生成差异SQL语句。 mysqldiff类似Linux下的diff命令,用来比较对象的定义是否相同,并显示不同的地方。 如果要比较数据库是否一致,可以用另外一个工具:mysqldbcompare...
  • 主要介绍了linux 比较两个文件夹diff不同 (diff命令, md5列表),比较文件夹diff,可以直接使用diff命令,也可以比较文件md5列表,下面通过实例给大家介绍下,感兴趣的朋友跟随脚本之家小编一起学习吧

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 84,910
精华内容 33,964
关键字:

diff