vue、react的diff算法以及遍历数据时的key绑定的作⽤
⽂章⽬录
经典⾯试题
react/vue中的key有什么作⽤?(key的内部原理是什么?)
为什么遍历列表时,key最好不要⽤index?
1. 虚拟DOM中key的作⽤:
简单的说:key是虚拟DOM对象的标识,在更新显⽰时key起着极其重要的作⽤。
详细的说:当状态中的数据发⽣变化时,react会根据【新数据】⽣成【新的虚拟DOM】,随后React进⾏【新虚拟DOM】与【旧虚拟DOM】的diff⽐较
⽐较规则如下:
旧虚拟DOM中到了与新虚拟DOM相同的key:
若虚拟DOM中内容没变, 直接使⽤之前的真实DOM
若虚拟DOM中内容变了, 则⽣成新的真实DOM,随后替换掉页⾯中之前的真实DOM
旧虚拟DOM中未到与新虚拟DOM相同的key
根据数据创建新的真实DOM,随后渲染到到页⾯
2. ⽤index作为key可能会引发的问题:
若对数据进⾏:逆序添加、逆序删除等破坏顺序操作,会产⽣没有必要的真实DOM更新 => 界⾯效果没问题, 但效率低。
如果结构中还包含输⼊类的DOM:会产⽣错误DOM更新 ==> 界⾯有问题。
注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅⽤于渲染列表⽤于展⽰,使⽤index作为key是没有问题的。
3. 开发中如何选择key
最好使⽤每条数据的唯⼀标识作为key, ⽐如id、⼿机号、⾝份证号、学号等唯⼀值。
如果确定只是简单的展⽰数据,⽤index也是可以的。
⽰例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>key的作⽤</title>
</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 -->
<script type="text/javascript" src="../js/babel.min.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>
*/
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]})
}
render(){
return(
<div>
<h2>展⽰⼈员信息</h2>
<button onClick={this.add}>添加⼀个⼩王</button>
<h3>使⽤index(索引值)作为key</h3>
<ul>
{
this.state.persons.map((personObj,index)=>{
return<li key={index}>{personObj.name}---{personObj.age}<input type="text"/></li>
})
}
</ul>
<hr/>
<hr/>
<h3>使⽤id(数据的唯⼀标识)作为key</h3>
<ul>
{
this.state.persons.map((personObj)=>{
return<li key={personObj.id}>{personObj.name}---{personObj.age}<input type="text"/></li> })
}
</ul>
</div>
)
}
}
</script>
</body>
</html>
慢动作
慢动作回放----使⽤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>
更新后的数据:
diff函数{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>
虚拟DOM
再说diff算法之前先来了解⼀下虚拟DOM:
虚拟DOM只保留了真实DOM节点的⼀些基本属性,和节点之间的层次关系,它相当于建⽴在jsvascript和DOM之间的⼀层”缓存“
虚拟DOM其实就是⼀个对象来描述DOM,通过对⽐前后两个对象的差异,最终只把变化的部分重新渲染,提⾼渲染的效率
什么是diff算法
React需要同时维护两棵虚拟DOM树:⼀棵树表⽰当前的DOM结构,另⼀棵在React状态变更将要重新渲染时⽣成。React通过⽐较这两棵树的差异,决定是否需要修改DOM结构,以及如何修改。
简单来说diff算法在虚拟DOM上实现,是虚拟DOM的加速器,提升性能的法宝。
Vue和React中diff算法的区别
vue和react的diff算法,都是忽略跨级⽐较,只做同级⽐较。
vue diff时调动patch函数,参数时vnode和oldVnode,分别代表新旧节点。
vue⽐对节点,当节点元素类型相同,但是className不同,认为是不同类型元素,删除重建,⽽react会认为是相同类型节点,只是修改节点属性。
vue的列表对⽐,采⽤从两端到中间的对⽐⽅式,⽽react则采⽤从左到右以此对⽐的⽅式。当⼀个集合,只是把最后⼀个节点移动到了第⼀个节点,react会把前⾯的节点依次移动,⽽vue只会把最后⼀个节点移动到第⼀个。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论