虚拟dom

1 .由于历史或者标准原因,也有可能是继承的关系,即使是一个简单的div元素,他的属性都会超过1百个,所以操作dom的时候所涉及到的性能问题,其实很严重,稍有不慎,就会导致页面元素的重排。
2 .dom上的结构,常用的属性,我们都可以使用对象结构简单的表示出来,而且原生js操作对象的速度非常快,而且简单。
3 .原生dom树-js对象-构建新的dom树。
4 .主要涉及到两个转化的问题,还有一个虚拟dom的diff优化。
5 .虚拟dom是真实dom的简单印射,对于一个真实的dom,我们只需要知道他的选择器,他的子节点,以及他的数据(属性,样式,类,事件等)我们就可以利用一个对象来描述这个真实的节点。
6 .用属性描述真实dom的各个特性,当他发生变化的时候,就会修改视图。
7 .以vnode节点模拟真实dom,对这颗抽象树进行创建节点,删除节点等操作,在这个过程中是不需要操作真实dom的,修改以后经过diff算法得出一些需要修改的最小单位,再将这些自小单位的视图进行更新,缉拿少许多不必要的dom操作。
8 .

diff原理

1 .状态变更,重新渲染了js对象结构,先对比js对象结构的位置,对新渲染的和就的树进行对比,记录两棵树的差异,记录下的不同就是我们需要真正的dom操作,然后把他们应用在真正的dom树上,页面发生变更。目的:视图的结构是整个全新渲染,但是最后的操作dom的时候只是变了不同的部分。
2 .这个他比较的地方是在用js生成的虚拟树上进行比较。
3 .在js和dom之间做一个缓存,可以类比cpu和硬盘,既然硬盘这么慢,那就在他们之间加个缓存,js只是操作虚拟dom,最后时间再把变更写入硬盘DOM

1 .用js结构表示dom数的结构;然后用这个树构建一个正真的dom树,插到文档里面去。
2 .当状态变更的时候,重新构造一棵新的对象树,然后用新的树和旧的树进行比较,记录两棵树的差异
3 .把2记录的差异用用到步骤1所构建的真正的dom树上,视图就完美更新了

构建js对象的部分,基于vue

1 .如何在把html代码转成js对象的时候就提前做好布局,比较的时候不需要生成dom树,只是来比较生成的前后数据有什么不一样不就可以了么,只需要改变数据发生变化的那一部分
2 .关键就是如何把渲染的数据和实际生成的dom一一对应起来,然后改的时候直接找索引就可以了。
3 .原本vue的vnode对象
4 .canvas防爬虫,为什么会有这么丧心病狂的方法

Vnode

export default class VNode {
  tag: string | void;
  data: VNodeData | void;
  children: ?Array<VNode>;
  text: string | void;
  elm: Node | void;
  ns: string | void;
  context: Component | void; // rendered in this component's scope
  functionalContext: Component | void; // only for functional component root nodes
  key: string | number | void;
  componentOptions: VNodeComponentOptions | void;
  componentInstance: Component | void; // component instance
  parent: VNode | void; // component placeholder node
  raw: boolean; // contains raw HTML? (server only)
  isStatic: boolean; // hoisted static node
  isRootInsert: boolean; // necessary for enter transition check
  isComment: boolean; // empty comment placeholder?
  isCloned: boolean; // is a cloned node?
  isOnce: boolean; // is a v-once node?

  constructor (
    tag?: string,
    data?: VNodeData,
    children?: ?Array<VNode>,
    text?: string,
    elm?: Node,
    context?: Component,
    componentOptions?: VNodeComponentOptions
  ) {
    /*当前节点的标签名*/
    this.tag = tag
    /*当前节点对应的对象,包含了具体的一些数据信息,是一个VNodeData类型,可以参考VNodeData类型中的数据信息*/
    this.data = data
    /*当前节点的子节点,是一个数组*/
    this.children = children
    /*当前节点的文本*/
    this.text = text
    /*当前虚拟节点对应的真实dom节点*/
    this.elm = elm
    /*当前节点的名字空间*/
    this.ns = undefined
    /*编译作用域*/
    this.context = context
    /*函数化组件作用域*/
    this.functionalContext = undefined
    /*节点的key属性,被当作节点的标志,用以优化*/
    this.key = data && data.key
    /*组件的option选项*/
    this.componentOptions = componentOptions
    /*当前节点对应的组件的实例*/
    this.componentInstance = undefined
    /*当前节点的父节点*/
    this.parent = undefined
    /*简而言之就是是否为原生HTML或只是普通文本,innerHTML的时候为true,textContent的时候为false*/
    this.raw = false
    /*静态节点标志*/
    this.isStatic = false
    /*是否作为跟节点插入*/
    this.isRootInsert = true
    /*是否为注释节点*/
    this.isComment = false
    /*是否为克隆节点*/
    this.isCloned = false
    /*是否有v-once指令*/
    this.isOnce = false
  }

  // DEPRECATED: alias for componentInstance for backwards compat.
  /* istanbul ignore next https://github.com/answershuto/learnVue*/
  get child (): Component | void {
    return this.componentInstance
  }
}

1 .以上是一个最基础的Vnode节点,可以作为其他派生类的基类

虚拟dom的diff

1 .前提:diff只发生在相同的层级,跨越层级的dom添加,删除,并不常见,一般都是兄弟之间的位置发生变化
2 .只会简单考虑同层节点的位置变换,对于不同层的节点,只有简单的创建和删除

判断sameVnode

1 .如果两个节点是sameNode,则保留旧的真实dom并对新旧虚拟节点的children进行diff,否则就删掉旧的虚拟节点对应的真是dom并替换为新虚拟节点对应的真实dom
2 .sameNode相同的条件:选择器相同,key相同,如果是input元素,还需要type类型相同,tag相同,isComment是否为注释节点,
3 .新旧虚拟节点children的diff是整个虚拟diff算法的核心,主要分为以下几种特殊情况。

1 .新虚拟节点有children,旧的虚拟dom没有children,可能有一个文字节点
1.1:清除文字节点,然后将新的虚拟节点children对应的真实节点添加到父节点

2.新虚拟dom没有children,旧的虚拟dom有chidren
2.1:直接删掉

3.旧虚拟dom text属性有定义,新虚拟节点text属性没定义而且没有children
3.1:删除旧节点的文本内容即可

4.新旧节点text属性有定义
4.1: 比较文本内容,不同则替换

5.新旧虚拟dom子节点都有children,比较chidlren

2 .各种虚拟dom算法的差别主要在于updateChildren方法实现的不同,snabbdom算法的特点是给新旧children分别提供了头尾两个指针,diff的过程中头尾指针分别向中间靠拢,当任一children的头指针超过尾指针的时候则diff结束

1.其实这个就是比较和更新观察json的方式。
2.有顺序的object怎么写
3.在遍历中,如果存在key,并且满足sameVnode,会将该dom节点进行复用,否则会创建一个新的dom节点
4.比较完之后,删除或者增加新的节点元素。
5.节点类型不同(这个单纯数据变化的时候应该不会有这个问题吧),这些操作都是出现在react中多一点,甚至是编写代码的时候多一点,实际上用户在操作这个网页的时候,是很少会出现这样的问题的,所以这一块的代码优先级好像没这么高吧。他的ui是完全基于状态来每次render整个界面而无需担心性能的问题。
6.节点类型相同,节点的属性不同。对属性进行重设而实现节点的转换。

3 .列表的增删改查这个要注意一下。

4 .
7a8a2c42ba0047c988c8dffc3bf97f85_th.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容