开发者社区> 问答> 正文

使用 React / Vue构建项目时为什么要在列表组件中写 key,其作用是什么?#前端面试

使用 React / Vue构建项目时为什么要在列表组件中写 key,其作用是什么?

展开
收起
Bill 2020-05-23 13:21:05 2541 0
1 条回答
写回答
取消 提交回答
  • 领取2折优惠劵,有几率免单哦!http://www.weilai.info/tool/326.html

    key是给每一个vnode的唯一id,可以依靠key,更准确, 更快的拿到oldVnode中对应的vnode节点。

      1. 更准确 因为带key就不是就地复用了,在sameNode函数 a.key === b.key对比中可以避免就地复用的情况。所以会更加准确。
      1. 更快 利用key的唯一性生成map对象来获取对应节点,比遍历方式更快。(这个观点,就是我最初的那个观点。从这个角度看,map会比遍历更快。)

    vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点。在vue的diff函数中(建议先了解一下diff算法过程)。 在交叉对比中,当新节点跟旧节点头尾交叉对比没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key => index 的map映射)。如果没找到就认为是一个新增节点。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点。一种一个map映射,另一种是遍历查找。相比而言。map映射的速度更快。 vue部分源码如下:

    // vue项目  src/core/vdom/patch.js  -488行
    // 以下是为了阅读性进行格式化后的代码
    
    // oldCh 是一个旧虚拟节点数组
    if (isUndef(oldKeyToIdx)) {
      oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
    }
    if(isDef(newStartVnode.key)) {
      // map 方式获取
      idxInOld = oldKeyToIdx[newStartVnode.key]
    } else {
      // 遍历方式获取
      idxInOld = findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
    }
    

    创建map函数

    function createKeyToOldIdx (children, beginIdx, endIdx) {
      let i, key
      const map = {}
      for (i = beginIdx; i <= endIdx; ++i) {
        key = children[i].key
        if (isDef(key)) map[key] = i
      }
      return map
    }
    

    遍历寻找

    // sameVnode 是对比新旧节点是否相同的函数
     function findIdxInOld (node, oldCh, start, end) {
        for (let i = start; i < end; i++) {
          const c = oldCh[i]
          
          if (isDef(c) && sameVnode(node, c)) return i
        }
      }
    
    2020-05-24 22:19:35
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
利用编译将 Vue 组件转成 React 组件 立即下载
React Native 全量化实践 立即下载
React在大型后台管理项目中的工程实践 立即下载