iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >html列表中的key属性有什么用
  • 681
分享到

html列表中的key属性有什么用

2024-04-02 19:04:59 681人浏览 安东尼
摘要

这篇文章给大家分享的是有关html列表中的key属性有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 diff 算法的时间复杂度是 O(n), 它的实现是基于以下两个假设

这篇文章给大家分享的是有关html列表中的key属性有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

diff 算法的时间复杂度是 O(n), 它的实现是基于以下两个假设:

两个 type 不同的元素生成不同的 DOM 树;

在两次渲染中,React 能通过 key 属性判断哪一个子元素保持不变;

本文内容围绕「假设 2」展开说明 diff 算法是怎么做到 O(n) 的时间复杂度的。

如果没有 key 属性

当遍历子元素列表的时候,React 会同时遍历新旧子元素列表,一旦遇到两个列表有不同的地方,就会生成一个 mutation。

<ul>

  <li>Duke</li>

  <li>Villanova</li>

</ul>

<ul>

  <li>Connecticut</li>

  <li>Duke</li>

  <li>Villanova</li>

</ul>

例如,当在子元素列表之前添加一个元素的时候,如果没有 key 属性,React 会同时遍历新旧子元素数组

第一个 li 标签有变化,更新;

第二个 li 标签有变化,更新;

最后插入第三个 li 标签;

这个算法的时间复杂度是 O(n),但是会导致很多不必要的 DOM 操作,性能低下。如果通过一种列表对比算法能避免掉不必要的 DOM 操作,就能优化性能。

Levenshtein Distance 算法

为了使用算法优化性能,让我们对上面的问题做一个抽象,旧的子元素列表:

[1, 2, 3, 4, 5] 

进行了一系列 DOM 节点的删除、插入、修改的操作之后,得到新的列表:

[6, 3, 1, 2, 5, 4] 

知道了新旧的顺序求最小的插入、删除、修改操作,这是数组的最小编辑距离问题。最常见的是 Levenshtein Distance 算法。

举一个例子:求 beaut( [公式] ) 和 ebau( [公式] ) 的最小编辑距离,其中 [公式] 是未知字符。动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。定义长度为「i - 1」的字符串 str1 和长度为「j - 1」的字符串 str2 的最小编辑距离为 [公式] ,那么 beaut( [公式] )和 ebau( [公式] ) 的最小编辑记 [公式] ,[公式] 能且只能基于下面三个状态:

「状态 1」 :beaut( [公式] ) 和 ebau 的最小编辑距离已知,记为 [公式] ;

「状态 2」:beaut 和 ebau( [公式] ) 的最小编辑距离已知,记为 [公式] ;

「状态 3」:beaut 和 ebau 的最小编辑距离已知,记为 [公式] ;

[公式] 和三个状态之间的关系分别为下面三个公式:

[公式]

[公式]

[公式]

解释一下第三个公式,在 [公式] 的情况下, [公式] ;如果 [公式] ,那么 [公式] 。那么上面三个公式值最小的那个就是 [公式] 的解。对照着下图看,也就是 [公式] 的值可以通过其上方,左边,左上对角线的值确定,公式如下:

[公式]

[公式]

[公式]

function minDistance(s1, s2) {

    const len1 = s1.length

    const len2 = s2.length

    let matrix = []

    for (let i = 0; i <= len1; i++) {

        // 构造二维数组

        matrix[i] = new Array()

        for (let j = 0; j <= len2; j++) {

            // 初始化

            if (i == 0) {

                matrix[i][j] = j

            } else if (j == 0) {

                matrix[i][j] = i

            } else {

                // 进行最小值分析

                let cost = 0

                if (s1[i - 1] != s2[j - 1]) { // 相同为0,不同置1

                    cost = 1

                }

                const temp = matrix[i - 1][j - 1] + cost

                matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, temp)

            }

        }

    }

    return matrix[len1][len2] //返回右下角的值

}

从上面的代码可以看出,LD 算法有两个嵌套的 for 循环,所以时间复杂度是 O(n*m),其中 n 为 str1 的长度,m 为 str2 的长度。如果采用 LD 算法,虽然能避免掉不必要的 DOM 操作,但是 diff 算法的时间复杂度就达不到线性了。

key 属性的引入思路

直接应用 LP 算法不能解决我们的问题。我们并不需要找到真正的最小编辑距离,而是需要找到一种算法,这个算法的时间复杂度必须是 O(n),并且能避免掉大部分的 DOM 操作,而前端的列表大部分的操作是子元素的移动。通过引入 key 属性唯一标识子元素,我们可以把最小编辑距离转化成:key 属性是对这个元素的唯一标识,在这个条件下,求新旧子元素列表的最小插入、删除、移动操作。这是一种启发式算法。

旧的子元素列表:

[{ key: 1, val: 1 }, { key: 2, val: 2 }, { key: 3, val: 3 }]

新的子元素列表:

[{ key: 4, val: 4 }, { key: 1, val: 1 }, { key: 3, val: 3 }, { key: 2, val: 2 }]

React 子元素近似最小编辑距离算法

为了寻找上面两个数组的近似最小编辑距离,React 的做法为,正向遍历新的子元素,用新的子元素的 key 值去旧的子元素中查找,如果没找到,就做插入;如果找到了就做移动操作;如果遇到旧的子元素在新的列表中找不到的情况,删除旧的子元素。算法的时间复杂度是 O(n)。 举一个例子,如下图,上一排是旧的子元素列表,下一排是新的子元素列表:

代码如下,正向遍历 nextChildren:

「元素 6」: 是新增元素,新增到 index = 0 的位置;

「元素 3」: 不变;

「元素 1」: 元素 1 在原数组中的位置在元素 3 之前,所以需要移动到元素 3 的后面;

「元素 2」: 元素 2 在原数组中的位置也位于 3 之前,移动到元素 1 的后面;

「元素 5」: 不变;

「元素 4」: 移动到 5 后面;

updateChildren() {

  // find removed

  const removednodes = findRemoved();

  var updates = [];

  var lastIndex = 0;

  var nextIndex = 0;

  var lastPlacedNode = null;

  for (const name in nextChildren) {

    var prevChild = prevChildren && prevChildren[name];

    var nextChild = nextChildren[name];

    if (prevChild === nextChild) {

      // 移动子元素

      if (prevChild._mountIndex < lastIndex) {

        updates.push({

          type: "MOVE_EXISTING",

          fromIndex: prevChild._mountIndex,

          toIndex: nextIndex,

          afterNode: afterNode

        })

      }

      lastIndex = Math.max(prevChild._mountIndex, lastIndex);

      prevChild._mountIndex = nextIndex;

    } else {

      if (prevChild) {

        lastIndex = Math.max(prevChild._mountIndex, lastIndex);

      }

      // 新增子元素

      updates.push({

        type: "INSERT_MARKUP",

        toIndex: nextIndex,

        content: nextChild

      });

    }

    nextIndex++;

    lastPlacedNode = getNativeNode(nextChild); // 获取 nextChild 对应的 DOM 节点

  }

  // 删除

  for (const name in removedNodes) {

    updates.push({

      type: "REMOVE_NODE",

      content: null,

      fromIndex: prevChildren[name]._mountIndex,

      fromNode: removedNodes[name]

    })

  }

}

Vue 的比较

Vue 对子元素的 diff 的思路和 React 一样,都引入了「key 是子元素的唯一标识」这一先决条件。在引入这一条件后,比 React 做了更多的优化,Vue 是从新老子元素列表的两头向中间遍历,并多做了一些特殊判断。就列表更新这一块,Vue 的性能高于 React。而在 Fiber 架构中,由于没有反向指针,React 不容易做到通过双向遍历优化子元素 diff 算法。

key 属性最佳实践

key 属性帮助 React 识别哪些元素改变了,哪些元素是新增的,哪些被删除了。元素列表中的元素的 key 值应该是稳定的,能起到唯一标识的作用。下面列举一些最佳实践:

1. 使用能在子元素列表之间能唯一标识这个子元素的字符串做为其 key 属性。用数组的 index 做为 key 值是一种反模式,需要避免。

const todoItems = todos.map((todo) =>

  <li key={todo.id}>

    {todo.text}

  </li>

);

2. key 会传递信息给 React ,但不会传递给你的组件。如果你的组件中需要使用 key 属性的值,请用其他属性名显式传递这个值。

const content = posts.map((post) =>

  <Post

    key={post.id}

    id={post.id}

    title={post.title} />

);

感谢各位的阅读!关于“html列表中的key属性有什么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

--结束END--

本文标题: html列表中的key属性有什么用

本文链接: https://www.lsjlt.com/news/90921.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • html列表中的key属性有什么用
    这篇文章给大家分享的是有关html列表中的key属性有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 diff 算法的时间复杂度是 O(n), 它的实现是基于以下两个假设...
    99+
    2022-10-19
  • HTML的列表属性有哪些
    这篇文章给大家分享的是有关HTML的列表属性有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1..无序列表无序列表是一个项目的列表,此列项目使用粗体圆点(典型的小黑圆圈)进行...
    99+
    2022-10-19
  • html技术中的列表属性有哪些
    这篇文章主要介绍了html技术中的列表属性有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、无序列表<ul><li&...
    99+
    2022-10-19
  • HTML中rel属性有什么用
    这篇文章给大家分享的是有关HTML中rel属性有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。由于发现有同学在微博转播和收藏这篇文章,所以回头来再审视下这篇随性翻译的文章,...
    99+
    2022-10-19
  • HTML中Face属性有什么用
    这篇文章主要介绍HTML中Face属性有什么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!   Face属性   face:文字字体   在HTML语言中,可以通过face属...
    99+
    2022-10-19
  • html中accept属性有什么用
    这篇文章主要介绍了html中accept属性有什么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。了解 accept 属...
    99+
    2022-10-19
  • HTML中marginheight属性有什么用
    在HTML中,marginheight属性用于设置iframe元素的上下外边距(margin)。它指定了iframe元素与其容器之间...
    99+
    2023-09-22
    HTML
  • HTML的表单属性是什么
    这篇文章将为大家详细讲解有关HTML的表单属性是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。表单是一个包含表单元素的区域。表单元素是允许用户在表单中(比如:文本域、...
    99+
    2022-10-19
  • HTML的href属性有什么用
    HTML的href属性用于指定链接的目标或资源。具体来说,href属性用于指定链接的URL地址,可以是一个相对路径或绝对路径。当用户...
    99+
    2023-10-10
    HTML
  • HTML的rowspan属性有什么用
    HTML中的rowspan属性用于指定单元格跨越的行数。它定义了单元格应该跨越的行数,从而将单元格合并为一个大单元格。这可以在HTM...
    99+
    2023-10-11
    HTML
  • html中Textarea defaultValue属性有什么用
    defaultValue属性用于设置文本区域(Textarea)的默认值。当页面加载时,文本区域中显示的文本即为defaultVal...
    99+
    2023-10-12
    html
  • html textarea属性有什么用
    HTML的textarea属性用于定义一个多行的文本输入控件。它具有以下用途:1. 显示和接受用户输入的多行文本:通过textare...
    99+
    2023-09-21
    html
  • HTML中router-link的to属性有什么用
    这篇文章将为大家详细讲解有关HTML中router-link的to属性有什么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 其实这个组件有点像原生 HTML 中的 a...
    99+
    2022-10-19
  • HTML的download属性有什么作用
    HTML的"download"属性用于指定一个链接的目标文件名,当用户点击该链接时,浏览器会将目标文件下载到本地而不是打开它。这个属...
    99+
    2023-10-12
    HTML
  • HTML的Style backgroundImage属性有什么用
    HTML的style backgroundImage属性用于设置元素的背景图片。通过设置该属性,可以将指定的图片作为元素的背景。可以...
    99+
    2023-10-12
    HTML
  • HTML的async属性有什么作用
    HTML的`async`属性用于指定脚本的异步加载方式。当`async`属性被添加到``元素上时,表示脚本将异步加载,不会阻塞页面的...
    99+
    2023-10-11
    HTML
  • HTML的colspan属性有什么用处
    在HTML中,`colspan`属性用于定义一个单元格横跨多少列。它可以应用于``或``元素。`colspan`属性的作用可以总结如...
    99+
    2023-10-11
    HTML
  • html的Select multiple属性有什么用
    HTML的``元素中的`multiple`属性用于指定是否允许多选。当设置了`multiple`属性时,用户可以通过按住Ctrl键(...
    99+
    2023-10-12
    html
  • html location.hash属性有什么作用
    HTML的`location.hash`属性用于获取或设置URL中的锚点部分(即#后面的内容)。锚点部分通常用于在页面内部进行导航或...
    99+
    2023-09-15
    html
  • HTML DOM background属性有什么用
    在HTML中,`background`属性是用于设置元素的背景样式的属性。它提供了一种简便的方式来指定元素的背景颜色、背景图像、重复...
    99+
    2023-10-12
    HTML
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作