一.验证Diffing算法
<!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 crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 引入prop-types,用于对标签属性进行限制 -->
<script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.js"></script>
<script type="text/babel">
// 生命周期回调函数=生命周期钩子函数=生命周期函数=生命周期钩子
class Time extends React.Component {
state = {date:new Date()}
componentDidMount(){
setInterval(() =>{
// 更新状态,
this.setState({date:new Date()})
},1000)
}
//1.3 render调用的时机:初始化渲染,状态更新之后
render(){
return (
<div>
<h1>hello</h1>
<input type="text"/>
<span>现在是:{this.state.date.toTimeString()}</span>
</div>
)
}
}
ReactDOM.render(<Time />,document.getElementById('test'))
</script>
</body>
</html>
结果:时间会不断变化,表示diffing算法在起作用,算法会逐层对比。只有标签会更新,但是若span标签中还有标签,其中的标签不一定会被更新。
二.key的作用
经典面试题:
1).react/vue中的key有什么作用?(key的内部原理是什么?)
2),为什么遍历列表时,key最好不要用index?
1.虚拟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,随后渲染到到贝面
2.用index作为key可能会引发的问题:
1,若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新==>界面效果没问题,但效率低。
2.如果结构中还包含输入类的DOM:会产生错误DOM更新 ==>界面有问题。
3.注意!如果不存在对数据的逆序添加、逆序除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
3.开发中如何选择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 crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 引入prop-types,用于对标签属性进行限制 -->
<script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.js"></script>
<script type="text/babel">
/*
经典面试题:
1).react/vue中的key有什么作用?(key的内部原理是什么?)
2),为什么遍历列表时,key最好不要用index?
1.虚拟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,随后渲染到到贝面
2.用index作为key可能会引发的问题:
1,若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新==>界面效果没问题,但效率低。
2.如果结构中还包含输入类的DOM:会产生错误DOM更新 ==>界面有问题。
3.注意!如果不存在对数据的逆序添加、逆序除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
3.开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
2.如果确定只是简单的展示数据。用index也是可以的。
*/
/* 慢动作回放,使用index索引值做key
数据: {id:1,name:'小张',age:18},
{id:2,name:'小李',age:19}
初始的虚拟DOM:
<li key={0}>{小张}----{18}<input type='text'/></li>
<li key={1}>{小李}----{19}<input type='text'/></li>
更新后的数据:{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19},
{id:3,name:'小王',age:20},
更新后的虚拟DOM:
<li key={0}>{小王}----{20}<input type='text'/></li>
<li key={1}>{小张}----{18}<input type='text'/></li>
<li key={2}>{小李}----{19}<input type='text'/></li>
--------------------------------------------------------------------
慢动作回放,使用id索引值做key
数据: {id:1,name:'小张',age:18},
{id:2,name:'小李',age:19}
初始的虚拟DOM:
<li key={1}>{小张}----{18}<input type='text'/></li>
<li key={2}>{小李}----{19}<input type='text'/></li>
更新后的数据:{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19},
{id:3,name:'小王',age:20},
更新后的虚拟DOM:
只更新一次真实DOM
<li key={3}>{小王}----{20}<input type='text'/></li>
<li key={1}>{小张}----{18}<input type='text'/></li>(复用)
<li key={2}>{小李}----{19}<input type='text'/></li>(复用)
*/
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]})
console.log(this.state,persons)
console.log(persons.length)
console.log(p)
}
//1.3 render调用的时机:初始化渲染,状态更新之后
render(){
return (
<div>
<h2>展示人员信息</h2>
<h3>使用索引值作为KEY</h3>
<button onClick={this.add}>添加一个小王信息</button>
<ul >
{
this.state.persons.map((personObj,index)=>{
return <li key={index}>{personObj.name}----{personObj.age} <input/></li>
})
}
</ul>
<hr/>
<hr/>
<h3>使用id(数据的唯一标识)作为KEY</h3>
<ul >
{
this.state.persons.map((personObj)=>{
return <li key={personObj.id}>{personObj.name}----{personObj.age}<input/></li>
})
}
</ul>
</div>
)
}
}
ReactDOM.render(<Person />,document.getElementById('test'))
</script>
</body>
</html>
结果:
添加前:
添加后:添加后,使用index作为索引值会导致信息错误