React中DOM的diffing算法
文章目录
前言
我们之前的学习中,一直知道用React可以通过虚拟DOM相同来避免一些非必要的页面渲染,其中就是基于diffing算法的,下面我们一起来探究一下,到底这个算法的执行流程是什么,以及关于key的注意事项一、Diffing算法的原理图?
二、diffing算法
1.显示时间案例
1.1 没有被渲染证明
在下面这个案例中,只有时间所在标签会被刷新,标题和input框并不会被重新渲染,一点直接的证明就是我在input框中输入东西,但是它并没有因为时间的变化,而被重新渲染清空
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</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 Time extends React.Component{
state={time:new Date()}
componentDidMount()
{
setInterval(()=>
{
this.setState({time:new Date()});
},1000)
}
render()
{
return (
<div>
<h1>欢迎来lmx实验室</h1>
<input/>
<span>今天的时间是{this.state.time.toTimeString()}</span>
</div>
)
}
}
ReactDOM.render(<Time/>,document.getElementById("test"));
</script>
</body>
</html>
1.2 整体还是查询嵌套标签再渲染呢?
那么上面重新渲染的是今天的时间是{this.state.time.toTimeString()}这句话,还是span里面的整个标签呢?其实渲染只能以标签为依据进行整体刷新,那么如果标签里面还嵌套标签呢?
答案很明显,如下所示,123里面的内容也不会重新渲染,这足以说明,diffing算法是很精明的,他会进行嵌套的循环比较,比较到input发现它的内容和之前的一样,那么就不会进行渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</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 Time extends React.Component{
state={time:new Date()}
componentDidMount()
{
setInterval(()=>
{
this.setState({time:new Date()});
},1000)
}
render()
{
return (
<div>
<h1>欢迎来lmx实验室</h1>
<input/>
<span>今天的时间是{this.state.time.toTimeString()}<input /></span>
</div>
)
}
}
ReactDOM.render(<Time/>,document.getElementById("test"));
</script>
</body>
</html>
2.key如何设置?
2.1 diffing如何操作react的渲染过程
2.2 以index为key的案例展示
首先我们实现一个以index为key实现的人员增加案例,这里为了更好的显示,我们把它加到数组前面
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</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={person:[{id:1,name:"小张",age:"18"},{id:2,name:"小李",age:"19"}]}
render()
{
return(
<div>
<button onClick={this.add}>点我添加小王</button>
<ul>{
this.state.person.map((one,index)=>
{
return <li key={index}>{one.name}------{one.age}</li>
})
}
</ul>
</div>
)
}
add=()=>
{
this.setState({person:[{id:3,name:"小王",age:20},...this.state.person]});
}
}
ReactDOM.render(<Person/>,document.getElementById("test"));
</script>
</body>
</html>
结果:我们会发现用index作key会出现几乎全部都需要重新渲染的情况,那么我们的效率就会变低
2.3 key设为id
会发现只有小王需要重新渲染,其他的都不用
2.4 key设为index产生的重大问题
加个input框
return(
<div>
<button onClick={this.add}>点我添加小王</button>
<ul>{
this.state.person.map((one,index)=>
{
return <li key={index}>{one.name}------{one.age} <input type="text"/></li>
})
}
</ul>
</div>
)
会发现点击添加之后,文本框还是和之前的顺序一样,并没有渲染,这个原因大概就是因为上述1.2了,key一样,key里面也有input,那么input就不需要渲染了,因为diffing算法的精明之处
总结
在本节中,我们深入知道为什么react能够节省渲染界面的数量,以及它的算法流程,以及一些注意事项,期待下一节的学习