文章目录
Diff算法原理
根据新旧虚拟DOM
的比较:
- 旧虚拟DOM中找到了与新虚拟DOM相同的位置的相同标签;
- 若虚拟DOM中内容没变,直接使用之前的真实DOM
- 若虚拟DOM中内容变了,则生成新的真实DOM随后替换掉页面中之前的真实DOM。
- 旧虚拟DOM中未找到与新虚拟DOM相同的位置的相同标签
创建新的真实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 type="text/javascript" src="../js/17.0.1/react.development.js"></script>
<script type="text/javascript" src="../js/17.0.1/react-dom.development.js"></script>
<script type="text/javascript" src="../js/17.0.1/babel.min.js"></script>
<script type="text/babel">
class Time extends React.Component{
state = {
date: new Date()}
componentDidMount(){
setInterval(()=>{
this.setState({
date: new Date()
})
},1000)
}
render(){
return(
<div>
<h1>hello</h1>
<input type="text"/>
<span>现在是:{
this.state.date.toTimeString()}</span>
</div>
)
}
}
ReactDOM.render(<Time/>,document.getElementById('test'))
</script>
<!-- 小结:
1. diff算法是根据虚拟dom来对比更新后的内容和更新前的内容的差距
2. diff算法的最小粒度是一个标签
-->
</body>
</html>
Diff算法过程:
注意
- DOM的diffing算法最小的粒度是
标签
。 - DOM的diffing算法对比的是很多层,逐层对比。
Diffing算法key的作用
案例: 展示列表
<!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 type="text/javascript" src="../js/17.0.1/react.development.js"></script>
<script type="text/javascript" src="../js/17.0.1/react-dom.development.js"></script>
<script type="text/javascript" src="../js/17.0.1/babel.min.js"></script>
<script type="text/babel">
class Person extends React.Component{
state = {
persons:[
{
id:1,name:'yang',age:19},
{
id:2,name:'cheng',age:20},
{
id:3,name:'wang',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>
<ul>
{
this.state.persons.map((person,index)=>{
return <li key={
index}>{
person.name}---{
person.age}</li>
})
}
</ul>
</div>
)
}
}
ReactDOM.render(<Person/>,document.getElementById('test'))
</script>
<!-- 和vue一样 -->
</body>
</html>
虚拟DOM中key的作用:
- 简单地说key是虚拟DOM的标识,在diffing算法中时key起着非常重要的作用
- 详细的说: 当状态中的数据发生变化时,react会根据新数据形成
新的虚拟DOM
,然后进行新虚拟DOM与旧虚拟DOM的diffing比较,规则如下:
1) 旧虚拟DOM中找到
了与新虚拟DOM相同的key
;
- 若虚拟DOM中内容没变,直接使用之前的真实DOM
- 若虚拟DOM中内容变了,则生成新的真实DOM随后替换掉页面中之前的真实DOM。
2) 旧虚拟DOM中未找到
与新虚拟DOM相同的key
; - 创建新的真实DOM,随后渲染到到页面。
上述代码的diff算法(key时index)
但是如果使用id值作为key,就不会有如上效率问题,可以实现真实DOM的复用
而且如果页面中有输入的节点
,如果key使用的是index,输入框的内容就会出现错乱。
小结
使用index作为key可能会引发问题
- 若对数据进行了逆序添加、逆序删除等破坏顺序的操作就会产生没有必要的真实DOM更新,造成效率的浪费
- 如果结构中还包含输入类的DOM,在列表前面添加数据的时候就hi产生错误的位置