vue、react的diff算法以及遍历数据时的key绑定的作用

文章目录

  • 经典面试题
    • 1. 虚拟DOM中key的作用:
    • 2. 用index作为key可能会引发的问题:
    • 3. 开发中如何选择key
  • 示例:
    • 慢动作
  • 虚拟DOM
  • 什么是diff算法
  • Vue和React中diff算法的区别

经典面试题

  • 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 -->
<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:
					
  • 小张---18
  • 小李---19
  • 更新后的数据: {id:3,name:'小王',age:20}, {id:1,name:'小张',age:18}, {id:2,name:'小李',age:19}, 更新数据后的虚拟DOM:
  • 小王---20
  • 小张---18
  • 小李---19
  • ----------------------------------------------------------------- 慢动作回放----使用id唯一标识作为key 初始数据: {id:1,name:'小张',age:18}, {id:2,name:'小李',age:19}, 初始的虚拟DOM:
  • 小张---18
  • 小李---19
  • 更新后的数据: {id:3,name:'小王',age:20}, {id:1,name:'小张',age:18}, {id:2,name:'小李',age:19}, 更新数据后的虚拟DOM:
  • 小王---20
  • 小张---18
  • 小李---19
  • */
    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> ) } } ReactDOM.render(<Person/>,document.getElementById('test')) </script> </body> </html>

    vue、react的diff算法以及遍历数据时的key绑定的作用_第1张图片

    慢动作

    • 慢动作回放----使用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:

  • 小王---20
  • 小张---18
  • 小李---19
  • 虚拟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只会把最后一个节点移动到第一个。

    你可能感兴趣的:(react,vue)