精华内容
下载资源
问答
  • 虚拟DOM和DOM Diffing算法 基本原理图 Diffing算法是通过不断比较虚拟DOM之间的差异,不断更新虚拟DOM.

    虚拟DOM和DOM Diffing算法

    基本原理图

    在这里插入图片描述

    Diffing算法是通过不断比较虚拟DOM之间的差异,不断更新虚拟DOM.

    展开全文
  • React 框架中diffing 算法的理解: 1: diffing 算法最小颗粒度是标签 (只可以精确到标签的位置) diffing 算法最小颗粒度是标签 (会一直递归循环遍历下去) 2:只要状态改变就会触发 render 函数 (实时修改状态) ...
    React 框架中diffing 算法的理解:
    1:  diffing 算法最小颗粒度是标签  (只可以精确到标签的位置)
        diffing 算法最小颗粒度是标签  (会一直递归循环遍历下去)
     
    2:只要状态改变就会触发 render 函数 (实时修改状态)  (状态修改就会触发render函数);
    在React/Vue 中 key属性有什么作用? (index 的内部原理是什么?)
    
    3: 为什么办理列表时: key 属性最好不要使用index?
       1: 虚拟DOM 中key属性的作用:
       (1): 简单的说: key属性是虚拟DOM对象的唯一标识, 在更新显示时key 属性起着重要的作用。
       (2): 详细的说: 当状态数据发生变化的时候, React 会根据[新数据] 生成的[新的虚拟DOM]
       (3): 随后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 是没问题的。
    
         4: 开发中如何如何选择key 值:
            1: 最好使用每一条数据唯一标识作为key 值, 比如:id 值,
            2: 如果确定只是简单展示数据,  使用 inde 也是可以的。
    ------------------------------------------------------------------------
    使用index 作为 key 属性的节点效率会低,  所有的DOM节点会渲染一边。效率会降低。
    但是使用 key 属性使用id 值, 虚拟DOM 渲染效率会高。
    展开全文
  • Diffing 算法 key

    2021-03-21 16:33:14
    Diffing 算法 当对比两棵树时,React 首先比较两棵树的根节点。不同类型的根节点元素会有不同的形态 当根节点为不同类型的元素时,React 会拆卸原有的树并且建立起新的树 当卸载一棵树时,对应的 DOM 节点也会被销毁...

    Diffing 算法

    当对比两棵树时,React 首先比较两棵树的根节点。不同类型的根节点元素会有不同的形态
    当根节点为不同类型的元素时,React 会拆卸原有的树并且建立起新的树
    当卸载一棵树时,对应的 DOM 节点也会被销毁
    当对比两个相同类型的 React 元素时,React 会保留 DOM 节点,仅比对及更新有改变的属性
    在这里插入图片描述

    key

    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:'tom',age:19}
                 ]
             }
             render(){
                 return(
                     <div>
                         <h2>展示人员信息</h2>
                         <h2>用index作为key</h2>
                         <button onClick={this.add}>添加人员</button>
                         <ul>
                          {
                              this.state.persons.map((personObj,index)=>{
                                  return <li key={index}>{personObj.name}-----{personObj.age} <input type="text"/></li>
                              })
                          }   
                         </ul>
                         <hr/>
                         <h2>展示人员信息</h2>
                         <h2>用id作为key</h2>
                         <ul>
                          {
                              this.state.persons.map((personObj)=>{
                                  return <li key={personObj.id}>{personObj.name}-----{personObj.age}<input type="text"/></li>
                              })
                          }   
                         </ul>      
                         
                     </div>
                 )
             }
             add =()=>{
                 const {persons} = this.state
                 const p = {id:3,name:'jack',age:20}
                 this.setState({persons:[p,...persons]})
             }
         }
        
      
    
    
    展开全文
  • React 的调和算法Diffing 算法

    千次阅读 2019-10-17 23:58:10
    React的调和算法,主要发生在render阶段,调和算法并不是一个特定的算法函数,而是指在调和过程中,为提高构建workInProcess树的性能,以及Dom树更新的性能,而采用的一种策略,又称diffing算法。 在React 的官网上...

    目录

    算法策略

    单节点diffing

    数组节点diffing

    key值的使用要求


    算法策略

    React的调和算法,主要发生在render阶段,调和算法并不是一个特定的算法函数,而是指在调和过程中,为提高构建workInProcess树的性能,以及Dom树更新的性能,而采用的一种策略,又称diffing算法。 在React 的官网上描述“Diffing” 算法时,提到了“diffing two trees”,但是在源码实现时,并不是创建好两棵树后,再从上往下的diffing这两棵树。这个diffing发生在搭建子节点时, 实际是新生成的ReactElement 与 current树上fibe节点的diffing。 为了将diffing算法的时间复杂度控制在O(n)(树diff的时间复杂度涉及到树的编辑距离,可以看这里), 采用了如下策略:

    1. 只比较同层级的节点,(貌似这一点没有在官网中提到)

    2. 对于单节点比较,如果当前节点type 和 key 不相同,不再比较其下子节点,直接删掉该节点及其下整棵子树,根据ReactElement重新生成节点树。因为React认为不同类型的组件生成的树形结构不一样,不必复用。

    3. 如果子节点是数组,可根据唯一的key值定位节点进行比较,这样即使子节点顺序发生变化,也可以根据key值进行复用。

    值得注意的是,所有节点的diffing都会比较key,key 默认值为null。若是没有设置,则null是恒等于null的,认为key是相同的。

    单节点diffing

    单个节点进行diffing时,会diffing两组属性:fibe.elementType vs ReactElement.type , fibe.key vs ReactElement.key, 如果这两组属性都相等,数据结构的物理空间会有如下复用逻辑(详见源码reconcileSingleElement函数):

    1. 如果current fibe 存在 alternate 节点,(这意味着这个fibe节点之前参与过调和),则复用该alternate节点的物理空间;否则需要clone current fibe节点,占用新的物理空间
    2. 对应的instance 或者 Dom 会被复用
    3. current fibe 下的child树也会被直接挂载过来(下一步递归子节点时,会被使用)

    如果两组属性有一个不相等:

    1. fibe 根据ReactElement重新创建
    2. 对应的instance和Dom 也会重建
    3. child 树全部删除。

    如果生成的ReactElement 是单节点,但是对应的current树上是多节点时,会从逐一查找有没有匹配的,找到匹配的,其他的都删除;找不到,全部删除。例如Couter组件有如下逻辑:当点击次数大于10时,隐藏点击按钮。当到达第10次时,span节点会被复用。

    class Counter extends React.Component{
        state={
            count:0
        }
        addCount = ()=>{
            const count = this.state.count+1;
            this.setState({count})
        }
        componentDidUpdate(){
            console.log("updated")
        }
        render(){
            return this.state.count < 10 ? [
                <button onClick={this.addCount}>点击</button>
                <span>点击次数:{this.state.count}</span>
            ]:<span>点击次数:{this.state.count}</span>;
        }
    }
    

    数组节点diffing

    数组节点进行diffing时,流程比较复杂:(源码见reconcileChildrenArray函数)

     

    中间有两次重要的遍历,第一次按index遍历,新旧节点依次比较,遇到key值不匹配的立即中断遍历。 第二次遍历,对剩下的旧节点建立 “key - 节点”的Map表,遍历剩下的新节点,按key值从表中查找旧节点进行比较。以下是三种case下,新旧节点匹配比较的情况。

     

    key值的使用要求

    从单节点和数组节点的diffing上看,key值主要是为了减少新建。为了保证diffing时新建旧节点能匹配上,key值使用时有如下注意:

    • 得稳定,如果key值每次都变化(比如使用了随机数),diffing时,新旧节全部匹配不上,将会引起大量的新建;
    • 必须得唯一,如果key值不唯一,在建立“key - 节点”的Map表时,会遗漏和错乱,导致页面更新错误。

    对于单节点,diffing时key值也会用到,不要认为其没用随便乱设置 也有一些不规范的用法,对单节点使用key值来实现组件的销毁和重建,但这种用法是不符合React的设计理念的。

    例如,有一个日志组件,内部拉取日志数据,对外部没有数据依赖。但是在需求迭代时,在同页面增加了审批操作,审批后,后端会新增一条日志数据,这时候会希望前端页面实时的展示新增的日志数据,会需要触发日志组件重新拉取数据。如果不使用向上提升数据的方式来解决问题,可以给该组件指定一个随机的key,当审批操作完成时,修改key值,则组件就会重新构建。但这种方式的开销较高,整个组件树都会销毁重建。可以采用其他解决方案代替,例如可以给该组件指定ref,当审批完成后,通过ref调用该组件的刷新函数,重新获取数据,更新组件。

    对于数组节点,key值主要是在子节点位置发生大的错位时,会起到关键作用。 对于普通的末尾新增,和末尾删除,第一次index遍历就可以匹配完,不会进入第二次key map的遍历。 因为key值对“稳定”和“唯一”性这两个要求,一般前端会需要后端对list数据提供一个唯一标识,对于聚合接口,会给后端增加额外工作,这种情况,可以先了解数据的变化特性,再决定是否真的需要设置key。

    对于上面的日志组件,日志是一个列表,新增的日志,都是插在第一行,如果不设置key,基本上所有的子节点都要更新。如果设置key,就需要后端服务为每一条日志增加“永远”惟一的标识符,例如id。曾经经历过一次因为key值的唯一性变化,导致数据更新时页面展示错误的案例。

    展开全文
  • react中DOM的diffing算法

    2021-08-09 11:27:55
    diffing算法渲染dom时会进行判断比较 如果当前标签内容未改变,就不会进行替换,如果改变就只替换改变的标签 diffing算法替换的最小单位是标签 下列情况 如在h2标签内有个span标签, diffing进行比较时,h2标签中的时间...
  • DOM的diffing算法只渲染更新的部分 使用index索引值作为key的弊端
  • React的diffing算法 在虚拟DOM转为真实DOM的时候,会想通过diffing算法进行一个比较。如果已经渲染过一次了,再次渲染的时候,会对相同key值的节点进行比较,如果内容相同,就会复用原来的那个真实DOM。 经典面试题...
  • 6-react-Diffing算法

    2021-05-13 11:56:19
    如下图所示,state状态一直在改变,每次改变都会...这就是react的diffing算法。 class Time extends React.Component { state = {date: new Date()} componentDidMount () { setInterval(() => { this.
  • 1. DOM 的 diffing 算法 知识一:DOM 的 diffing 算法 验证 Diffing 算法 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>验证diff算法</title> </head&...
  • React(四)- ReactDOM的Diffing算法和React脚手架一. React中的key1.1 diffing规则二. React脚手架2.1 初始化React脚手架 React系列文章导航 一. React中的key 从案例出发,从key的角度来引入diffing算法案例1: ...
  • Diffing算法 用与对比两棵虚拟dom树,将旧dom更新为新dom,如果用传统的dfs算法转换需要O(n3),而diff只需要O(n) 目前 Virtual DOM 的主流 diff算法 基本一致,Vue整合了snabbdom库,React使用了reconcilation ...
  • 验证Diffing算法

    2021-04-27 17:59:12
    <div id="test"></div> <!-- 引入react核心库 --> <script src="../js/17.0.1/react.development.js">...-- 引入react-dom,用于支持react操作dom -->...script src="../js/17.0.1/react-dom...
  • _DOM的Diffing算法: 虚拟DOM中key的作用: 1). 简单的说: key是虚拟DOM对象的标识, 在更新显示时key起着极其重要的作用。 2). 详细的说: 当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】, ...
  • 在某一时间节点调用 React ...diffing算法; 1.React中key有什么作用,内部原理是什么,为什么遍历列表时,key最好不使用index? 1. 虚拟DOM中key的作用: 1). 简单的说: key是虚拟DOM对象的标识, 在更新显示时key起着
  • 1、什么是DOM的diffing算法 1)diffing意为different,react、vue,都是先生成虚拟DOM之后,再转换为页面的真实DOM。 2)DOM更新时,react会先与之前的虚拟DOM做对比,和之前一样的节点可复用,不会重新渲染;然而...
  • 虚拟DOM与DOM Diffing算法key的作用虚拟DOM中key的作用:用index作为key可能会引发的问题:开发中如何选择keyDiffing 算法比对不同类型的元素比对同一类型的元素 key的作用 虚拟DOM中key的作用: 简单的说: key是...
  • 前几天面试问道 react 的相关知识,对我打击比较大,感觉对 react 认识非常肤浅,所以在这里重新梳理一下,想想之前没有仔细...重新学习 React (二) Diffing 算法及性能优化 重新学习 React (三) 深入理解 jsx 重新...
  • [React]Day07—React的 Diffing 算法经典面试题一、 react/vue的key有什么作用?(Key的内部原理是什么?)二、 为什么遍历列表时,key最好不要用index? <!DOCTYPE html> <html lang="en"> <head> ...
  • 1. 验证react的diffing算法 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>验证diff算法</title> </head> <body> <!-- 准备好一个“容器” ...
  • 了解 Diffing 算法

    2020-03-08 22:27:01
    下一步,调用 render() 方法,diff 算法将在之前的结果以及新的结果中进行递归。 对子节点进行递归 在默认条件下,当递归 DOM 节点的子元素时,React 会同时遍历两个子元素的列表;当产生差异时,生成一个 ...
  • 虚拟DOM与DOM Diffing算法效果基本原理图 1. 组件的生命周期 1.1 理解 组件从创建到死亡它会经历一些特定的阶段。 React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。 我们在定义组件时,会...
  • 十九、彻底理解React如何重新处理DOM(Diffing算法) React提供了一个声明式的API,所以你不必担心每次DOM更新时内部会修改哪些东西。虽然在React中并不是那么明显地告诉你具体如何实现的,不过这也让编写应用变得...
  • 本文描述了在实现 React 的 “diffing算法中我们做出的设计决策以保证组件满足更新具有课预测性,以及在复杂业务下依然保持应用的高性能性. 设计动力 在某一时间节点调用 React 的 render() 方法,...
  • diff 算法是 React 提升渲染性能的一种优化算法,在 React 中有着很重要的地位,也不止于 React ,在 Vue 中也有 diff 算法,似乎没有差别。在最近的 React 学习中,学到了 diff 算法,感觉视频中的内容有点浅,对 ...
  • 在react/vue中key有什么作用?内部原理是什么? 虚拟dom中key的作用 简单的来说key就是虚拟dom对象中的标识,在更新显示时key有很重要的作用 原理:当状态中的数据发生改变的时候,react会根据【新数据】生成新的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 497
精华内容 198
关键字:

diffing算法