zoukankan      html  css  js  c++  java
  • 虚拟dom和diff算法

    https://github.com/livoras/blog/issues/13

    这里简单记录一些要点和理解:

      一个dom元素中有许多属性,操作dom是很耗资源的,而操作自定义的js对象是很高效。所以在操作dom之间多加一层“虚拟dom”,建立虚拟dom与dom的关联,把直接操作dom转换为操作虚拟dom,然后把最终的虚拟dom关联到dom上,关联的方式是把差异应用到dom上。

      一个js对象来描述一个dom,只需要tagName、props以及children即可。

    一个虚拟dom应用,有如下初始化过程

    1. 通过js(如react的jsx)确定好虚拟dom
    2. 根据虚拟dom生成实际的dom树,写到body中  

    在js中对虚拟dom进行操作,每次操作会生成一颗新的虚拟dom树,虚拟dom的新树和旧树进行对比,找出差异,然后这些差异会被应用到实际的dom上,完成界面的变更。

    对比方式:

      同层次节点对比,深度优先。

    差异的类型以及处理方式

    1. 标签名变更,则整个节点统一进行替换,里面的子节点也跟着替换。
    2. 标签的属性变更,把变更的属性应用上去。
    3. 文本节点内容变更,直接替换即可。
    4. 子元素个体的增加、删除、移动。

    如何检测子元素个体的变更?

      为每个个体都加上一个标识符key,在当前兄弟节点中这个key要唯一,这样才能在当前的所有children中唯一标识。标识完成后,问题就可以转化为字符串的对比问题了,这里对比只能得出列表的差异(增加删除移动等)。接着继续进行相同key的节点的对比,到这里可见差异的对比是递归的。进行子元素个体的标识,有利于dom的复用,如果不指定,算法会认为两个子元素列表完全不一样,会全部重新渲染,这就很耗费性能了。

    “如果元素没有重排,使用数组的索引作为key效果不错”。如何理解这句话呢?

      没重排的意思是,结构体的展示次序不发生变化,而仅仅是结构体中少量属性发生变更。在这种情况下,两个列表元素依次一一对应,找出差异,然后把这些差异按次序应用到列表dom上。如果元素有重排,而且使用了索引作为key,两个列表中相同索引的结构体会完全不同,这样一进行对比,可能会得出一大堆的差异,再将这些差异应用上去可能会比较慢,我感觉其实这些说的都只是相对而已。

    如何把差异应用(patch)到实际dom上?

      最开始初始化的时候,根据虚拟dom生成实际的dom,两者的结构层次是一样的,而差异是通过对虚拟dom深度优先对比出来的,应用当然是对实际dom进行深度优先,然后把差异应用上去。

      

  • 相关阅读:
    opencv目录
    qt5-编译并添加opencv库
    java版gRPC实战之二:服务发布和调用
    java版gRPC实战之一:用proto生成代码
    github搜索技巧小结
    client-go实战之五:DiscoveryClient
    client-go实战之四:dynamicClient
    client-go实战之三:Clientset
    client-go实战之二:RESTClient
    client-go实战之一:准备工作
  • 原文地址:https://www.cnblogs.com/hellohello/p/7988346.html
Copyright © 2011-2022 走看看