啰嗦啰嗦React/Vue里key这个东东

前言:最近面试经常聊到key的概念,一个非常常见的知识点,但还是遇到了一部分并不理想的情况。所以我想再啰嗦啰嗦,交流分享一下我的理解和认识。


key这个概念,无论是React还是Vue,写过的同学,应该没有不知道的。对于key的理解,大部分人都描述的相差无二,基本都是在渲染数组列表的场景,条目项在添加、删除或调整顺序时,前后便于对应起来,提供diff以及渲染性能。

下面就以React为例唠一唠,先参考一下官网文档的说明:

“key” 是在创建元素数组时,需要用到的一个特殊字符串属性。key 帮助 React 识别出被修改、添加或删除的 item。应当给数组内的每个元素都设定 key,以使元素具有固定身份标识。

只需要保证,在同一个数组中的兄弟元素之间的 key 是唯一的。

不要将 Math.random() 之类的值传递给 key。重要的是,在前后两次渲染之间的 key 要具有“固定身份标识”的特点,以便 React 可以在添加、删除或重新排序 item 时,前后对应起来。理想情况下,key 应该从数据中获取,对应着唯一且固定的标识符,例如 post.id。

这个说道在创建元素数组时,因为这一点,应该有相当一部分人就局限于此了。我们多想一想,这里实际上只是一个特别有代表性,而且便于理解释义的一个场景case。多理解理解上面的解释,帮助React识别,使元素具有固定身份标识,唯一性,为什么需要这样呢,达成这样的条件,React它是想做什么?从这里我深入想一想,研究一下。

首先 SHOW ME YOUR CODE!

元素数组的case,个人认为就没有必要跟大家絮叨了,官网以及网上都能找到很多参考,这里我们拿非数组场景来研究一下。

只做核心代码逻辑展示,上下文省略,需要的自行下去完善。
定义一个示例组件:CompA.js

import { useEffect, useState } from "react";

export default function CompA({ name }) {
  const [val, setVal] = useState("");
  useEffect(() => {
    console.log(name, "mounted!!!");
  }, []);
  return (
    <div className="App">
      <h2>CompA name: {name}</h2>
      <input
        style={{ width: "200px" }}
        value={val}
        onChange={(ev) => setVal(ev.target.value)}
        placeholder="代表组件内部状态, 初始状态"
      />
      {val ? <p>当前组件内部状态变化:val = {val}</p> : null}
    </div>
  );
}

示例展示容器: App.js

import "./styles.css";
import CompA from "./CompA";
import { useState } from "react";

export default function App() {
  const [key, setKey] = useState("");
  const [name, setName] = useState("");
  const [cname, setCname] = useState("default");
  const [ckey, setCkey] = useState("a1");

  return (
    <div className="App">
      <h1>React key</h1>
      <input
        placeholder="请输入key"
        value={key}
        onChange={(ev) => setKey(ev.target.value)}
      />
      <button onClick={() => setCkey(key)}>修改CompA实例的key</button>
      <br />
      <input
        placeholder="请输入name"
        value={name}
        onChange={(ev) => setName(ev.target.value)}
      />
      <button onClick={() => setCname(name)}>修改CompA实例的props: name</button>
      <CompA key={ckey} name={cname} />
    </div>
  );
}
  1. 运行效果,初始状态
    运行效果,初始状态

    控制台打印内容:
    default CompA mounted!!! 
    
  2. 修改组件状态,效果如下,ComA组件实例内部状态发生了变化
    修改组件状态,展示效果

    此时控制台无新的打印
  3. 改变一下CompA组件的props属性看看
    修改props,展示效果

    此时组件CompA实例一直是没有变化,还是最初构建的实例对象,因为控制台依然没有新的打印。
  4. 现在我们改变一下key,试试看
    修改key,展示效果

    此时控制打印内容: (第一行未#1打印的)
    default CompA mounted!!! 
    porps change CompA mounted!!! 
    

结果很明了了,#4仅仅是改变了key,props还是name='props change',从打印及执行展示效果上来看,组件重新构建实例化了,props还是原来的,但因为重新实例化,内部状态没有了,回到了初始状态。这点其实在我们实际开发中很有用的,不仅限于元素数组。
线上查看:https://codesandbox.io/s/react-key-hwq6y

最终总结一下

React拿key做什么的呢,再回看官网解释, 重点我们不要仅关注元素数组,而唯一的固定身份标识前后对应,这点才是核心。
在我面试的时候,很多候选人还会说到diff算法,理论上说的很多都没有问题,甚至没有破绽。但是否真正理解了diff算法以及key的概念,对应上实际case,就有一部分断线了。
React根据key,唯一确定定位对应的组件实例,通过key更快速定位,综上因此就是:

  • key相同,复用保持原实例,props或者内部state状态变化,react只更新组件对应变化的属性。
  • key不同,销毁之前的组件实例,再重新构建新的组件实例。(前提上下文,仅针对当前组件,组件数组情况可对比参考官网)

技术最重要的还是应用,要灵活应用好,首先我们要真正的理解它是怎么运行的,进而逻辑原理,最终能做到触类旁通,举一反三,知其然,知其所以然。

参考

React官网-术语key


个人理解整理,欢迎交流,如有错误之处,还请斧正。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 一、简介 1、 Vue.js 是什么 参考网址:https://cn.vuejs.org/v2/guide/ind...
    满天繁星_28c5阅读 466评论 0 1
  • 简介 上一节我们完成了从 0 开始搭建一个企业级 React 项目的全部内容,项目是有了,但是我们一直都没有近距离...
    vv_小虫虫阅读 282评论 0 2
  • vue vue是一套用于构建用户界面的渐进式框架(渐进式框架的大概意思就是你可以只用我的一部分,而不是用了我这一点...
    BigTooth_3611阅读 454评论 0 0
  • 此文项目代码:https://github.com/bei-yang/I-want-to-be-an-archit...
    LM林慕阅读 1,553评论 0 6
  • react有一个特殊属性key 应用场景根据数组动态创造,不确定数量,顺序的子节点时使用需要对某一组件的更新操作强...
    mengxr阅读 649评论 0 1