1、key是什么

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.

key 是用来帮助 react 识别哪些内容被更改、添加或者删除。key 需要写在用数组渲染出来的元素内部,并且需要赋予其一个稳定的值。稳定在这里很重要,因为如果 key 值发生了变更,react 则会触发 UI 的重渲染。这是一个非常有用的特性。key就是元素的唯一标识,相当于身份证一样。

2、key的作用

key赋值一般采用两种方式,一种是赋值index(索引),一种是赋值id(这里用id表示稳定标识),我们举个例子来看看两者之间的区别。

key=index例子:

ToDo组件:

import React from 'react'
import { number, object } from 'prop-types'

const ToDo = ({ id, createAt }) => (
  <tr>
    <td>
      <label>{id}</label>
    </td>
    <td>
      <input />
    </td>
    <td>
      <label>{createAt.toTimeString()}</label>
    </td>
  </tr>
)

ToDo.propTypes = {
  id: number.isRequired,
  createAt: object.isRequired
}

export default ToDo

ToDoList组件:

import React, { Component } from 'react'

import ToDo from '../ToDo'

export default class ToDoList extends Component {
  state = {
    todoCounter: 1,
    list: [
      { id: 1, createAt: new Date() }
    ]
  }

  addStart = () => {
    this.setState(prevState => ({
      list: [{ id: prevState.todoCounter + 1, createAt: new Date() }, ...prevState.list],
      todoCounter: prevState.todoCounter + 1
    }))
  }

  addEnd = () => {
    this.setState(prevState => ({
      list: [...prevState.list, { id: prevState.todoCounter + 1, createAt: new Date() }],
      todoCounter: prevState.todoCounter + 1
    }))
  }

  sortEarly = () => {
    this.setState(prevState => ({
      list: prevState.list.sort((a, b) => {
        return a.createAt - b.createAt
      })
    }))
  }

  sortLate = () => {
    this.setState(prevState => ({
      list: prevState.list.sort((a, b) => {
        return b.createAt - a.createAt
      })
    }))
  }

  render () {
    return (
      <div>
        <code>key=index</code>
        <br />
        <button onClick={this.addStart}>add new to start</button>
        <button onClick={this.addEnd}>add new to end</button>
        <button onClick={this.sortEarly}>sorted by earliest</button>
        <button onClick={this.sortLate}>sorted by latest</button>
        <table>
          <tr>
            <th>ID</th>
            <th>Input</th>
            <th>create at</th>
          </tr>
          {
            this.state.list.map((item, index) => (
              <ToDo key={index} {...item}></ToDo>
            ))
          }
        </table>
      </div>
    )
  }
}

结果:
index.gif

key=id例子:
我们将<ToDo key={index} {...item}></ToDo>改成<ToDo key={item.id} {...item}></ToDo>,结果为:
id1.gif

我们可以看到key=idkey=index时应用程序表现结果是不相同的,不相同之处表现在input输入值有没有随着排序而改变。我们来解释一下产生这种结果的原因(元素类型相同时,key值相同的元素标识同一个元素)。

当key=index时
index.png

当key=id时
id.png

一个是元素位置没变,重新渲染数据;一个是位置变了,数据没变,只需要移动位置,所以才导致上面现象。当我们的列表数据非常庞大时,重新渲染的代价是很高的,正确的使用key值可以帮助我们减少渲染量,做到及时响应,这也是react的一大优点。

参考:
https://medium.com/@adhithiravi/why-do-i-need-keys-in-react-lists-dbb522188bbb
https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318
https://zhuanlan.zhihu.com/p/45091185
https://juejin.im/post/5a7c04746fb9a063461fe700
https://juejin.im/post/59abb01c518825243f1b6dad


记得要微笑
1.9k 声望4.5k 粉丝

知不足而奋进,望远山而前行,卯足劲,不减热爱。