啰嗦啰嗦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


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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

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