一、验证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></title>
</head>
<body>
<div id="app"></div>
<!-- 加载 React。-->
<!-- 注意: 部署时,将 "development.js" 替换为 "production.min.js"。-->
<!--react核心库-->
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<!--react扩展库 用于支持react操作DOM-->
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<!--babel 让支持jsx转js-->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!--用于对组件标签属性进行限制 全局会多一个对象PropTypes-->
<script src="https://unpkg.com/prop-types@15.6.2/prop-types.js"></script>
<script type="text/babel">
//创建组件
class Timer extends React.Component{
state={date:new Date()}
componentDidMount(){
console.log("ok");
setInterval(() => {
this.setState({date:new Date()})
}, 1000);
}
render (){
//只有整个span标签(不只是内容还有span标签)更新了,h1和input没有变化没有更新还是原来的真实DOM,在input中输入内容内容不变所以没有更新DOM还是原来的
return(
<div>
<h1>hello</h1>
<input type="text"/>
<span>现在是:{this.state.date.toTimeString()}</span>
</div>
)
}
}
//2.渲染虚拟DOM到页面
ReactDOM.render(<Timer />,document.getElementById('app'))
</script>
</body>
</html>
二、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></title>
</head>
<body>
<div id="app"></div>
<!-- 加载 React。-->
<!-- 注意: 部署时,将 "development.js" 替换为 "production.min.js"。-->
<!--react核心库-->
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<!--react扩展库 用于支持react操作DOM-->
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<!--babel 让支持jsx转js-->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!--用于对组件标签属性进行限制 全局会多一个对象PropTypes-->
<script src="https://unpkg.com/prop-types@15.6.2/prop-types.js"></script>
<script type="text/babel">
/*
2.2 关于key的经典面试题
1). react/vue中的key有什么作用?(key的内部原理是什么?)
2). 为什么遍历列表时,key最好不要用index?
2.2.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.2.2 用index作为key可能会引发的问题
若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
如果结构中还包含输入类的DOM:
会产生错误DOM更新 ==> 界面有问题
注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,
仅用于渲染列表用于展示,使用index作为key是没有问题的
2.2.3 开发中如何选择key?
最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值
如果确定只是简单的展示数据,用index也是可以的
*/
/*
慢动作回放-----使用index索引值作为key
初始数据:
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19}
初始的虚拟DOM:
<li key=0>小张----18</li>
<li key=1>小李----19</li>
更新后的数据
{id:3,name:'小王',age:20}
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19}
更新后的虚拟DOM:(小王是先遍历的所以是0)
<li key=0>小王----18</li>
<li key=1>小张----18</li>
<li key=2>小李----19</li>
旧的(初始)虚拟DOM和更新后的新的虚拟DOM对比
明明小张和小李可以复用,但是用了index作为key,导致索引值变了,导致了没有必要的真实DOM更新。
慢动作回放-----使用id(唯一标识)作为key
初始数据:
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19}
初始的虚拟DOM:
<li key=1>小张----18</li>
<li key=2>小李----19</li>
更新后的数据
{id:3,name:'小王',age:20}
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19}
更新后的虚拟DOM:(小王是先遍历的所以是0)
<li key=3>小王----18</li>
<li key=1>小张----18</li>
<li key=2>小李----19</li>
旧的(初始)虚拟DOM和更新后的新的虚拟DOM对比
没有key等于3的虚拟DOM那就转为真实DOM放到页面
问旧的虚拟DOM你那有key等于1和key等于2的虚拟DOM吗,有,那么就直接复用了,不再生成新的真实DOM了也不往页面上放了
*/
//创建组件
class Person extends React.Component{
state={
person:[
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19}
]
}
add=()=>{
const {person}=this.state
const p={id:person.length+1,name:'小王',age:20}
this.setState({person:[p,...person]})
}
render (){
return(
<div>
<h2>展示人员信息</h2>
<button onClick={this.add}>添加一个小王</button>
<h3>使用index索引值作为key</h3>
<ul>
{
this.state.person.map((personObj,index)=>{
return <li key={index}>{personObj.name}----{personObj.age}<input type="text"/></li>
})
}
</ul>
<br/><br/>
<h3>使用id(数据的唯一标识)作为key</h3>
<ul>
{
this.state.person.map((personObj)=>{
return <li key={personObj.id}>{personObj.name}----{personObj.age}<input type="text"/></li>
})
}
</ul>
</div>
)
}
}
//2.渲染虚拟DOM到页面
ReactDOM.render(<Person />,document.getElementById('app'))
</script>
</body>
</html>