React之DOM的diff算法
Posted Icy Hunter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React之DOM的diff算法相关的知识,希望对你有一定的参考价值。
文章目录
DOM的diff算法
React展示前端首先将DOM转换为虚拟DOM,然后再生成页面上的真实DOM,因此当DOM更新时,React会先更新虚拟DOM,然后将新的虚拟DOM与旧的进行对比,如果遇到相同的,页面上对应的DOM就不需要变动,如果遇到不相同的,那么就更新对应页面上的DOM。
这样的好处就是当一个页面内容很多,但是每次只需要更新一点点内容时,React就会有比较好的性能。
react中的key有什么作用?
虚拟DOM中key的作用:
1) 简单的说:key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。、
2) 详细的说:当状态中的数据发生变化时,react会根据新数据生成新的虚拟DOM,随后React进行新虚拟DOM与旧虚拟DOM的diff比较比较规则如下:
a. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
(1). 若虚拟DOM中的内容没变,直接使用之前的真实DOM
(2). 若虚拟DOM中的内容变了,则生成真实DOM,随后替换掉页面中之前的真实DOM
b. 旧虚拟DOM中未找到与新虚拟DOM相同的key,根据数据创建新的真实DOM,随后渲染到网页。
为什么遍历列表时,key最好不要用index?
用index作为key可能会引发的问题:
1)若对数据进行:逆序添加、逆序删除等破环顺序操作,会产生没有必要的真实DOM更新 界面效果没问题,单效率低
2) 如果结构中还包含输入类的DOM,会产生错误DOM更新界面有问题
3) 注意!如果不存在对数据逆序添加、逆序删除等破环顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
开发中如何选择key?
1.最好使用每条数据唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
2.如果确定只是简单的展示数据,用index也是可以的
实例
用个实例来感受一下。
假设这里是逆序添加元素,就会导致一些问题:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="test"></div>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script src="../js/prop-types.js"></script>
<script type="text/babel">
class Person extends React.Component
state =
persons:[
id:1, name:"小张", age:18,
id:2, name:"小李", age:19,
]
add = () =>
const persons = this.state;
const p = id:persons.length+1, name:"小王", age:20
this.setState(persons:[p,...persons])
render()
return (
<div>
<h2>展示人员信息</h2>
<button onClick=this.add>添加一个小王</button>
<h3>使用index(索引值)作为key</h3>
<ul>
this.state.persons.map((personObj, index) =>
return <li key=index>personObj.name----personObj.age<input type="text"/></li>
)
</ul>
<hr/>
<hr/>
<h3>使用id(数据唯一标识)作为key</h3>
<ul>
this.state.persons.map((personObj, index) =>
return <li key=personObj.id>personObj.name----personObj.age<input type="text"/></li>
)
</ul>
</div>)
ReactDOM.render(<Person/>, document.getElementById("test"))
</script>
</body>
</html>
运行后
页面文本框输入对应的信息,然后点击按钮
发现逆序添加元素时
用index会导致错位,因为
index原本是 小张0,小李1,现在逆序添加小王,那么现在小王为0,小张1,小李2,导致DOM得重新生成,而输入框的内容并未改变,则保留,就会导致这样的错误。
但是如果顺序添加元素,这个实例其实也没什么问题:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="test"></div>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script src="../js/prop-types.js"></script>
<script type="text/babel">
class Person extends React.Component
state =
persons:[
id:1, name:"小张", age:18,
id:2, name:"小李", age:19,
]
add = () =>
const persons = this.state;
const p = id:persons.length+1, name:"小王", age:20
this.setState(persons:[...persons,p])
render()
return (
<div>
<h2>展示人员信息</h2>
<button onClick=this.add>添加一个小王</button>
<h3>使用index(索引值)作为key</h3>
<ul>
this.state.persons.map((personObj, index) =>
return <li key=index>personObj.name----personObj.age<input type="text"/></li>
)
</ul>
<hr/>
<hr/>
<h3>使用id(数据唯一标识)作为key</h3>
<ul>
this.state.persons.map((personObj, index) =>
return <li key=personObj.id>personObj.name----personObj.age<input type="text"/></li>
)
</ul>
</div>)
ReactDOM.render(<Person/>, document.getElementById("test"))
</script>
</body>
</html>
运行结果:
总结
所有还是需要将key设置为唯一标识,不能简单用index,因为可能到时候会出现bug。
以上是关于React之DOM的diff算法的主要内容,如果未能解决你的问题,请参考以下文章