本章内容

目录

一、了解 Diff 算法二、key 值的重要性三、为什么不建议使用 index 做 key 值

上一节我们初步了解了 React中的”虚拟 DOM“ ,本节我们来说一说”虚拟DOM“中的”Diff算法“

一、了解 Diff 算法

在上一篇中,我们有讲到:当 state或者 props数据变化时会生成新的 ”虚拟DOM“,然后”旧虚拟DOM“和”新虚拟DOM“进行比对。那么怎么进行比对呢?答案是”使用 Diff 算法“。

”Diff算法“:我们把两个 ”JS对象“比对的算法叫做 ”Diff 算法“

问:1、”虚拟DOM“ 什么时候被比对

答:当”数据“发生变化的时候,新旧”虚拟DOM“才会进行比较

问2、那什么时候”数据“会发生变化

答:state 或者 props 改变时(代码中使用了 setState() 时,数据发生变化)

问3、为什么 React 的 setState() 设计成”异步“呢

答:为了提高 React 底层的性能。比如说如果我们在间断很短的时间内调用 setState() ,

如果设计成 ”同步“,那么就有三次更新比对”虚拟DOM“的过程,

如果设计成”异步“,就可以合并成”1次“,只做一次”虚拟DOM“的比对,然后去更新一次DOM,避免了性能的消耗

问4、新旧”虚拟DOM“如何进行比对呢

答:采用”同层比较“的方式。首先从最顶层开始,如果一致,就会去比较第二层,以此类推。

如果顶层比较时,不一致,则会直接将”原始DOM“进行全部替换。

这样”比较“和”替换“的暴力方式,看着好像挺浪费性能的(一层不一致就全部替换,很多DOM都没被复用),但由于”同层比较“的算法简单,因此比较的速度很快,性能一下就被提升了

二、key 值的重要性

在之前的案例中,我们循环渲染列表时,会在循环项上廷加一个 key。那为什么或者有必要添加这个 key呢?答案是:有必要!!!因为在”虚拟DOM“的”Diff算法“中,这个 key为循环的每一项添加了一个卫衣标识,可以有效提高”虚拟DOM“的比对性能

假设我们现在有个数组,里面有 5 个数据项。当界面第一次循环渲染时,这5个数据会被映射成 5个”虚拟DOM“节点,生成一个小的”原始虚拟 DOM树“ 当数据变化时,会生成一个”新的虚拟DOM“ 然后”新旧虚拟 DOM“进行比对(理想状态) 如果此时每一项数据都没有设置 key值,那么节点和节点的关闭就不确定,需要一个一个的去比较。相反,如果设置了 key值,那么每一项被唯一标识。这样我们就可以将”相同key标识的项“去比对,这无疑加快了比较速度

三、为什么不建议使用 index 做 key 值

指的注意的是,上面提升”性能“的关键点是”同样的节点取了相同的名字“,如果说使用 index作为 key值,我们不能保证相同的节点拥有同样的名字

打开我们的 TodoList案例,在列表循环时,使用 index作为 key值,然后运行打开浏览器

// TodoList.js 文件

import React, { Component, Fragment } from "react";

import TodoItem from "./TodoItem";

class TodoList extends Component{

constructor(props) {

super(props)

this.deleteData = this.deleteData.bind(this)

this.addListData = this.addListData.bind(this)

this.changeInputValue = this.changeInputValue.bind(this)

this.state = {

inputValue: '',

list: []

}

}

render() {

return (

请输入要进行的事项:

    {this.getTodoItem()}

)

}

getTodoItem() {

return this.state.list.map((item, index) => {

// 1、使用 index 作为 key 值

return

})

}

deleteData(index) {

this.setState((prevState) => {

const list = [...prevState.list]

list.splice(index, 1)

return {list}

})

}

addListData() {

this.setState((prevState) => ({

list: [...prevState.list, prevState.inputValue],

inputValue: ''

}))

}

changeInputValue(e) {

const value = e.target.value

this.setState(() => ({inputValue: value}))

}

}

export default TodoList

在输入框中输入一些内容,观察界面效果

此时:

Oli --> key: 0

qdywxs --> key: 1

Oli and qdywxs --> key: 2

删除 Oli后

此时:

qdywxs --> key: 0

Oli and qdywxs --> key: 1

所以说,使用 index作为 key值,这就造成了同一节点,前后 key值不一样,那么这两个节点就无法建立联系,也就起不到根据key 值快速比对内容的效果了 假如我们使用唯一的key值,节点的标识是稳定的,也就在比对过程中 key有了重要作用

到此,本章内容结束!

推荐阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: