diffing算法渲染dom时会进行判断比较 如果当前标签内容未改变,就不会进行替换,如果改变就只替换改变的标签
diffing算法替换的最小单位是标签
下列情况 如在h2标签内有个span标签, diffing进行比较时,h2标签中的时间值是一直改变的 所以进行替换
但是h2中的input标签并未改变, 所以在替换h2标签内容时 会再检索下一层子标签span
检测到只是h2标签内的时间值改变 而子标签内容并未改变,它会只替换时间值,并不替换子标签中的未改变的内容
<!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>
<style>
.title{
width: 200px;
background-color: coral;
}
</style>
</head>
<body>
<!-- 准备一个"容器" -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom 用于支持react操作dom -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将ajax转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types 用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
//1.创建组件
class Demo extends React.Component{
//初始化状态
state = {
Time:new Date()
}
componentDidMount(){
setInterval(()=>{
this.setState({
Time:new Date()
})
},1000)
}
//状态初始化和更新之后
render() {
console.log('Demo--render');
return (
<div>
<h1>hello</h1>
<input/>
{
// diffing算法渲染dom时会进行判断比较 如果当前标签内容未改变,就不会进行替换,如果改变就只替换改变的标签
// diffing算法替换的最小单位是标签
// 下列情况 如在h2标签内有个span标签, diffing进行比较时,h2标签中的时间值是一直改变的 所以进行替换
// 但是h2中的input标签并未改变, 所以在替换h2标签内容时 会再检索下一层子标签span
// 检测到只是h2标签内的时间值改变 而子标签内容并未改变,它会只替换时间值,并不替换子标签中的未改变的内容
}
<h2>当前时间:{this.state.Time.toTimeString()}<span><input/></span></h2>
</div>
)
}
}
ReactDOM.render(<Demo/>,document.getElementById('test'))
</script>
</body>
</html>
经典面试题:
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作为唯一标识进行渲染
这种情况下 如果有一千次渲染 添加一条数据进去 就要重新渲染1001次
而使用自定义的id则不会出现这种情况
两种相比 第二种效率更高
<!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>key</title>
<style>
.title{
width: 200px;
background-color: coral;
}
</style>
</head>
<body>
<!-- 准备一个"容器" -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom 用于支持react操作dom -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将ajax转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types 用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/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:3,name:'小王',age:20},
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19},
更新数据后的虚拟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>
*/
//1.创建组件
class Demo extends React.Component{
//初始化状态
state = {
list:[
{id:1,name:'小张',age:19},
{id:2,name:'小李',age:10},
{id:3,name:'小康',age:30},
]
}
add(){
const {list} = this.state
const p1 = {id:list.length+1,name:'小欧',age:12}
setInterval(()=>{
this.setState({
list:[p1,...list]
})
},1000)
}
//状态初始化和更新之后
render() {
console.log('Demo--render');
return (
<div>
<h1>人员展示</h1>
<button onClick={this.add.bind(this)}>添加</button>
<ul>
{this.state.list.map((item,index)=>{
return <li key={index}>{item.name}---{item.age}</li>
})}
</ul>
</div>
)
}
}
ReactDOM.render(<Demo/>,document.getElementById('test'))
</script>
</body>
</html>
使用id作为索引值
如果是对数据进行添加
可以在添加时添加在数组的尾部
如数组.push()
或者
如果是用index并在结构中包含输入类的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>key</title>
<style>
.title{
width: 200px;
background-color: coral;
}
</style>
</head>
<body>
<!-- 准备一个"容器" -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom 用于支持react操作dom -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将ajax转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types 用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/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:3,name:'小王',age:20},
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19},
更新数据后的虚拟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:3,name:'小王',age:20},
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19},
更新数据后的虚拟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>
*/
//1.创建组件
class Demo extends React.Component{
//初始化状态
state = {
list:[
{id:1,name:'小张',age:19},
{id:2,name:'小李',age:10},
{id:3,name:'小康',age:30},
]
}
add(){
const {list} = this.state
const p1 = {id:list.length+1,name:'小欧',age:12}
setInterval(()=>{
this.setState({
list:[p1,...list]
})
},1000)
}
//状态初始化和更新之后
render() {
console.log('Demo--render');
return (
<div>
<h1>人员展示</h1>
<button onClick={this.add.bind(this)}>添加</button>
<h3>使用index(索引值)作为key</h3>
<ul>
{this.state.list.map((item,index)=>{
return <li key={index}>{item.name}---{item.age}<input type='text' /></li>
})}
</ul>
<hr/>
<hr/>
<h3>使用id(数据的唯一标识)作为key</h3>
<ul>
{this.state.list.map((item,index)=>{
return <li key={item.id}>{item.name}---{item.age}<input type='text' /></li>
})}
</ul>
</div>
)
}
}
ReactDOM.render(<Demo/>,document.getElementById('test'))
</script>
</body>
</html>