十一、DOM的Diffing算法

一、验证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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值