当前位置: 首页 > news >正文

关于VirtualDom的知识点

记录一个前端大神的笔记,逐步学习 

原文 github.com/livoras/blo…

故事

作为React的核心概念之一,virtual dom从某种意义上改变了前端的现有体系。大部分人把virtual dom当做一种性能提升策略,因为它可以有效的减少直接操作DOM带来的消耗,从而提升脚本的执行效率。但是实际上,virtual dom并不完全是避免DOM操作的消耗,有的情况下,直接操作DOM可能来的更快,而virtual dom的真正意义,在于把直接的DOM操作和js编程,提炼成一个抽象层,virtual dom是对js操作DOM的抽象,对于今后的前端编程而言,developer无需再直接操作DOM,而是通过virtual dom去操作,这是它真正的意义。

VirtualDom真的快吗

VirtualDom最常被提及的优势就是它的效率高,原因是对js对象的操作要比对原生dom的操作要快很多,有了虚拟dom,我们更新视图前可以比较两颗虚拟dom树的差异,只更新差异部分,减少了对真正dom节点的操作,所以提高了效率。 然而事实上是不一定的,我们必须知道建立虚拟dom树本身和比较差异都是需要消耗时间的,如果不采用virtualdom,我们更新视图一般用innerHtml方法。这两种方法的更新时间可以粗略表示如下:

innerHtml:渲染成htmlstring + 重新创建所有dom

VirtualDom:渲染成VirtualDom + 比较新旧Dom树差异 + 必要dom更新 

所以两者的快慢实际取决于需要渲染的界面大小和更新部分的多少,可以看出innerHtml这种重新创建所有的dom的方式在只有几行数据改变时可能会造成大量浪费,所以从整体来看VirtualDom更优,但如果只是渲染静态界面,则innerHtml反而更快。

VirtualDom实现

一个简单VirtualDom机制,只需分为3个部分,第一步是建立VirtualDom树,第二步是设计比较新旧两个树之间差异的算法,最后一步是将差异更新到真正的视图部分。

创建VirtualDom树 

一般情况下我们可以将DOM树表示为一个JavaScript的Object对象,如下有一颗DOM树

<ul id='list'>
    <li class='item'>Item 1</li>
    <li class='item'>Item 2</li>
    <li class='item'>Item 3</li>
</ul>复制代码

该DOM树对应的JS对象如下:

var element = {
    tagName: 'ul', // 节点标签名
    props: { // DOM的属性,用一个对象存储键值对
        id: 'list'
    },
    children: [ // 该节点的子节点
        {tagName: 'li', props: {class: 'item'}, children: ["Item 1"]},
        {tagName: 'li', props: {class: 'item'}, children: ["Item 2"]},
        {tagName: 'li', props: {class: 'item'}, children: ["Item 3"]},
    ]
}复制代码

两相比较,我们可以发现,我们将DOM中的任一元素表示为:

{ type: ‘…’, props: { … }, children: [ … ] }复制代码

而DOM中的纯文本节点会被表示为普通的JavaScript中的字符串。不过这还是一个简单的DOM树,如果是一个较大型的树,我们就需要一个辅助函数来构造结构

function Element(tagName,props,children){
    this.tagName=tagName
    this.props=props
    this.children=children
}复制代码

我们用上面的构造函数来完成DOM数

const ul = new Element('ul',{id:'list'},[
    new Element('li',{class:'item'},['item 1']),
    new Element('li',{class:'item'},['item 1']),
    new Element('li',{class:'item'},['item 1'])
])复制代码

我们再来编写一个方法,来真正的渲染DOM

Element.prototype.render=function(){
    // 根据tagName构建
    var el = document.createElement(this.tagName)
    var props = this.props
    // 设置节点的DOM属性
    for (var propName in props) {
        var propValue = props[propName]
        el.setAttribute(propName, propValue)
    }

    var children = this.children || []

    children.forEach(function (child) {
        var childEl = (child instanceof Element)
            ? child.render() // 如果子节点也是虚拟DOM,递归构建DOM节点
            : document.createTextNode(child) // 如果字符串,只构建文本节点
        el.appendChild(childEl)
    })

    return el
}复制代码

这时,我们再把ul插入到真正的节点中:

const rootEl = ul.render()
document.body.appendChild(rootEl)复制代码

比较两棵虚拟DOM树的差异

比较两棵DOM树的差异是 Virtual DOM 算法最核心的部分,这也是所谓的 Virtual DOM 的 diff 算法。两个树的完全的 diff 算法是一个时间复杂度为 O(n^3) 的问题。但是在前端当中,你很少会跨越层级地移动DOM元素。所以 Virtual DOM 只会对同一个层级的元素进行对比

相关文章:

  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • [CF703D]Mishka and Interesting sum/[BZOJ5476]位运算
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 生成、打包、部署和管理应用程序及类型(3):将模块合并成程序集
  • windows下使用nginx调试简介
  • Ajax 知识
  • 什么软件可以提取视频中的音频制作成手机铃声
  • TypeScript(ES6) 的一些使用的小技巧
  • git远程分支回退
  • 开源SQL-on-Hadoop系统一览
  • Terraform入门 - 3. 变更基础设施
  • 【刷算法】LeetCode-26.删除排序数组中的重复项
  • SpiderData 2019年2月16日 DApp数据排行榜
  • matlab-基础 矩阵 同时修改多个元素
  • micropython esp8266 烧录
  • 分享一款快速APP功能测试工具
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • 2017年终总结、随想
  • Android系统模拟器绘制实现概述
  • Angular数据绑定机制
  • Asm.js的简单介绍
  • Facebook AccountKit 接入的坑点
  • iOS 系统授权开发
  • Java小白进阶笔记(3)-初级面向对象
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • MySQL的数据类型
  • spring security oauth2 password授权模式
  • 猴子数据域名防封接口降低小说被封的风险
  • 检测对象或数组
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 浅谈web中前端模板引擎的使用
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 找一份好的前端工作,起点很重要
  • Mac 上flink的安装与启动
  • # C++之functional库用法整理
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • #define
  • #stm32驱动外设模块总结w5500模块
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (一)Dubbo快速入门、介绍、使用
  • (转)fock函数详解
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具
  • [2016.7.Test1] T1 三进制异或
  • [AutoSar NVM] 存储架构
  • [BZOJ4554][TJOI2016HEOI2016]游戏(匈牙利)
  • [C#7] 1.Tuples(元组)