保健励志美文体育育儿作文
投稿投诉
作文动态
热点娱乐
育儿情感
教程科技
体育养生
教案探索
美文旅游
财经日志
励志范文
论文时尚
保健游戏
护肤业界

Vue虚拟DOM什么是虚拟DOM?如何实现一个虚拟DOM虚拟

  虚拟DOM的优势首先是可以对真实的元素节点进行抽象,抽象成VNode(虚拟节点),这样方便后续对其进行各种操作因为对于直接操作DOM来说是有很多的限制的,js每操作一次操作DOM,会使DOM进行重排或者重绘,每次操作都会消耗大量资源,比如diff、clone等等,但是使用JavaScript编程语言来操作这
  些,就变得非常的简单我们可以使用JavaScript来表达非常多的逻辑,而对于DOM本身来说是非常不方便,用js操作虚拟DOM,DOM元素会在内存中更改,等所有操作结束之后,只需要一次更新即可,提高性能其次是方便实现跨平台,包括你可以将VNode节点渲染成任意你想要的节点如渲染在canvas、WebGL、SSR、Native(iOS、Android)上并且Vue允许你开发属于自己的渲染器(renderer),在其他的平台上渲染虚拟DOM的渲染过程
  templaterender渲染函数虚拟DOM(VNode)真实DOM浏览器展示一、什么是虚拟DOM
  虚拟DOM(VirtualDOM)这个概念相信大家都不陌生,从React到Vue,虚拟DOM为这两个框架都带来了跨平台的能力(ReactNative和Weex)
  实际上它只是一层对真实DOM的抽象,以JavaScript对象(VNode节点)作为基础的树,用对象的属性来描述节点,最终可以通过一系列操作使这棵树映射到真实环境上
  在Javascript对象中,虚拟DOM表现为一个Object对象。并且最少包含标签名(tag)、属性(attrs)和子元素对象(children)三个属性,不同框架对这三个属性的名命可能会有差别
  创建虚拟DOM就是为了更好将虚拟的节点渲染到页面视图中,所以虚拟DOM对象的节点与真实DOM的属性一一照应
  在vue中同样使用到了虚拟DOM技术
  定义真实DOMpclassp节点内容h3{{foo}}h3
  实例化vueconstappnewVue({el:app,data:{foo:foo}})
  观察render的render,我们能得到虚拟DOM(functionanonymous(){with(this){returnc(p,{attrs:{id:app}},〔c(p,{staticClass:p},〔v(节点内容)〕),v(),c(h3,〔v(s(foo))〕)〕)}})
  通过VNode,vue可以对这颗抽象树进行创建节点,删除节点以及修改节点的操作,经过diff算法得出一些需要修改的最小单位,再更新视图,减少了dom操作,提高了性能
  在vue中,每一个组件都有一个render函数,这个函数会生成一个虚拟dom,这就意味着每一个组件都对应一个虚拟dom树。
  二、为什么需要虚拟DOM
  DOM是很慢的,其元素非常庞大,页面的性能问题,大部分都是由DOM操作引起的
  真实的DOM节点,哪怕一个最简单的p也包含着很多属性,可以打印出来直观感受一下:
  这个主要是由vue结构所决定的,在vue中,渲染试图会调用render函数,不仅在创建视图的时候被调用,当组件所依赖的数据或者属性发生了改变的时候,也会调用render函数,如果是使用真实的dom,当创建,修改,删除,插入dom的话是非常消耗性能的,如下所示,当修改一个js对象远比操作真实的dom要有效率的多。运行结果:
  由此可见,操作DOM的代价仍旧是昂贵的,频繁操作还是会出现页面卡顿,影响用户的体验
  举个例子:
  你用传统的原生api或jQuery去操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程
  当你在一次操作时,需要更新10个DOM节点,浏览器没这么智能,收到第一个更新DOM请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程
  而通过VNode,同样更新10个DOM节点,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性attach到DOM树上,避免大量的无谓计算
  很多人认为虚拟DOM最大的优势是diff算法,减少JavaScript操作真实DOM的带来的性能消耗。虽然这一个虚拟DOM带来的一个优势,但并不是全部。虚拟DOM最大的优势在于抽象了原本的渲染过程,实现了跨平台的能力,而不仅仅局限于浏览器的DOM,可以是安卓和IOS的原生组件,可以是近期很火热的小程序,也可以是各种GUI
  三、如何实现虚拟DOM
  首先可以看看vue中VNode的结构
  源码位置:srccorevdomvnode。jsexportdefaultclassVNode{tag:stringvoid;data:VNodeDatavoid;children:?ArrayVNode;text:stringvoid;elm:Nodevoid;ns:stringvoid;context:Componentvoid;renderedinthiscomponentsscopefunctionalContext:Componentvoid;onlyforfunctionalcomponentrootnodeskey:stringnumbervoid;componentOptions:VNodeComponentOptionsvoid;componentInstance:Componentvoid;componentinstanceparent:VNodevoid;componentplaceholdernoderaw:boolean;containsrawHTML?(serveronly)isStatic:boolean;hoistedstaticnodeisRootInsert:boolean;necessaryforentertransitioncheckisComment:boolean;emptycommentplaceholder?isCloned:boolean;isaclonednode?isOnce:boolean;isavoncenode?constructor(tag?:string,data?:VNodeData,children?:?ArrayVNode,text?:string,elm?:Node,context?:Component,componentOptions?:VNodeComponentOptions){当前节点的标签名this。tagtag当前节点对应的对象,包含了具体的一些数据信息,是一个VNodeData类型,可以参考VNodeData类型中的数据信息this。datadata当前节点的子节点,是一个数组this。childrenchildren当前节点的文本this。texttext当前虚拟节点对应的真实dom节点this。elmelm当前节点的名字空间this。nsundefined编译作用域this。contextcontext函数化组件作用域this。functionalContextundefined节点的key属性,被当作节点的标志,用以优化this。keydatadata。key组件的option选项this。componentOptionscomponentOptions当前节点对应的组件的实例this。componentInstanceundefined当前节点的父节点this。parentundefined简而言之就是是否为原生HTML或只是普通文本,innerHTML的时候为true,textContent的时候为falsethis。rawfalse静态节点标志this。isStaticfalse是否作为跟节点插入this。isRootInserttrue是否为注释节点this。isCommentfalse是否为克隆节点this。isClonedfalse是否有vonce指令this。isOncefalse}DEPRECATED:aliasforcomponentInstanceforbackwardscompat。istanbulignorenexthttps:github。comanswershutolearnVuegetchild():Componentvoid{returnthis。componentInstance}}
  这里对VNode进行稍微的说明:所有对象的context选项都指向了Vue实例elm属性则指向了其相对应的真实DOM节点
  vue是通过createElement生成VNode
  源码位置:srccorevdomcreateelement。jsexportfunctioncreateElement(context:Component,tag:any,data:any,children:any,normalizationType:any,alwaysNormalize:boolean):VNodeArrayVNode{if(Array。isArray(data)isPrimitive(data)){normalizationTypechildrenchildrendatadataundefined}if(isTrue(alwaysNormalize)){normalizationTypeALWAYSNORMALIZE}returncreateElement(context,tag,data,children,normalizationType)}
  上面可以看到createElement方法实际上是对createElement方法的封装,对参数的传入进行了判断exportfunctioncreateElement(context:Component,tag?:stringClassComponentFunctionObject,data?:VNodeData,children?:any,normalizationType?:number):VNodeArrayVNode{if(isDef(data)isDef((data:any)。ob)){process。env。NODEENV!productionwarn(Avoidusingobserveddataobjectasvnodedata:{JSON。stringify(data)}Alwayscreatefreshvnodedataobjectsineachrender!,context)returncreateEmptyVNode()}objectsyntaxinvbindif(isDef(data)isDef(data。is)){tagdata。is}if(!tag){incaseofcomponent:issettofalsyvaluereturncreateEmptyVNode()}。。。supportsinglefunctionchildrenasdefaultscopedslotif(Array。isArray(children)typeofchildren〔0〕function){datadata{}data。scopedSlots{default:children〔0〕}children。length0}if(normalizationTypeALWAYSNORMALIZE){childrennormalizeChildren(children)}elseif(SIMPLENORMALIZE){childrensimpleNormalizeChildren(children)}创建VNode。。。}
  可以看到createElement接收5个参数:context表示VNode的上下文环境,是Component类型tag表示标签,它可以是一个字符串,也可以是一个Componentdata表示VNode的数据,它是一个VNodeData类型children表示当前VNode的子节点,它是任意类型的normalizationType表示子节点规范的类型,类型不同规范的方法也就不一样,主要是参考render函数是编译生成的还是用户手写的
  根据normalizationType的类型,children会有不同的定义if(normalizationTypeALWAYSNORMALIZE){childrennormalizeChildren(children)}elseif(SIMPLENORMALIZE){childrensimpleNormalizeChildren(children)}
  simpleNormalizeChildren方法调用场景是render函数是编译生成的
  normalizeChildren方法调用场景分为下面两种:render函数是用户手写的编译slot、vfor的时候会产生嵌套数组
  无论是simpleNormalizeChildren还是normalizeChildren都是对children进行规范(使children变成了一个类型为VNode的Array),这里就不展开说了
  规范化children的源码位置在:srccorevdomhelpersnormalziechildren。js
  在规范化children后,就去创建VNodeletvnode,ns对tag进行判断if(typeoftagstring){letCtorns(context。vnodecontext。vnode。ns)config。getTagNamespace(tag)if(config。isReservedTag(tag)){如果是内置的节点,则直接创建一个普通VNodevnodenewVNode(config。parsePlatformTagName(tag),data,children,undefined,undefined,context)}elseif(isDef(CtorresolveAsset(context。options,components,tag))){component如果是component类型,则会通过createComponent创建VNode节点vnodecreateComponent(Ctor,data,context,children,tag)}else{vnodenewVNode(tag,data,children,undefined,undefined,context)}}else{directcomponentoptionsconstructorvnodecreateComponent(tag,data,context,children)}
  createComponent同样是创建VNodeexportfunctioncreateComponent(Ctor:ClassComponentFunctionObjectvoid,data:?VNodeData,context:Component,children:?ArrayVNode,tag?:string):VNodeArrayVNodevoid{if(isUndef(Ctor)){return}构建子类构造函数constbaseCtorcontext。options。baseplainoptionsobject:turnitintoaconstructorif(isObject(Ctor)){CtorbaseCtor。extend(Ctor)}ifatthisstageitsnotaconstructororanasynccomponentfactory,reject。if(typeofCtor!function){if(process。env。NODEENV!production){warn(InvalidComponentdefinition:{String(Ctor)},context)}return}asynccomponentletasyncFactoryif(isUndef(Ctor。cid)){asyncFactoryCtorCtorresolveAsyncComponent(asyncFactory,baseCtor,context)if(Ctorundefined){returncreateAsyncPlaceholder(asyncFactory,data,context,children,tag)}}datadata{}resolveconstructoroptionsincaseglobalmixinsareappliedaftercomponentconstructorcreationresolveConstructorOptions(Ctor)transformcomponentvmodeldataintopropseventsif(isDef(data。model)){transformModel(Ctor。options,data)}extractpropsconstpropsDataextractPropsFromVNodeData(data,Ctor,tag)functionalcomponentif(isTrue(Ctor。options。functional)){returncreateFunctionalComponent(Ctor,propsData,data,context,children)}extractlisteners,sincetheseneedstobetreatedaschildcomponentlistenersinsteadofDOMlistenersconstlistenersdata。onreplacewithlistenerswith。nativemodifiersoitgetsprocessedduringparentcomponentpatch。data。ondata。nativeOnif(isTrue(Ctor。options。abstract)){constslotdata。slotdata{}if(slot){data。slotslot}}安装组件钩子函数,把钩子函数合并到data。hook中installComponentHooks(data)实例化一个VNode返回。组件的VNode是没有children的constnameCtor。options。nametagconstvnodenewVNode(vuecomponent{Ctor。cid}{name?{name}:},data,undefined,undefined,undefined,context,{Ctor,propsData,listeners,tag,children},asyncFactory)if(WEEXisRecyclableComponent(vnode)){returnrenderRecyclableComponentTemplate(vnode)}returnvnode}微提下createComponent生成VNode的三个关键流程:构造子类构造函数CtorinstallComponentHooks安装组件钩子函数实例化vnode
  虚拟dom是如何转换为真实dom的?
  在组件渲染的时候会调用render函数,这个函数会生成一个虚拟的dom,再根据这个虚拟的dom来生成真实的dom,然后将这个真实的dom给挂载到页面的合适的部位,总的来说创建真实的dom是必不可少的一部分,如果视图只需要渲染一次,后续数据的改变不会影响到视图的改变,vue的效率其实要比真实操作dom的效率要低,因为vue还要创建一个虚拟的dom,但是如果组件内有响应式的数据,当数据发生改变的时候,就会调用render函数来生成一个新的虚拟dom树,将新的虚拟dom树和旧的虚拟dom树进行对比,然后找到必须修改的虚拟dom,最后根据修改的虚拟dom,来修改真实的dom,这样就保证了对真实的dom操作达到最小的改变,
  在进行新的虚拟dom和旧的虚拟dom对比的算法是patch算法,它会找到新的虚拟dom树和旧的虚拟dom树之间的差别。
  模板和虚拟dom的关系?
  在vue中有一个compile模块,这个模块将template字符串编译成render函数,render函数最后返回一个虚拟dom。
  编译过程分为两步:
  (1)将template转换为AST(抽象语法树)
  (2)将AST转换为render函数
  使用

高二写人作文一路有你相陪凤凰浴火而盘涅,而我因你而蜕变!题记你是谁?我忘了,我不知道你的一切,不知道你为何来到我的身边,不知道你为何会陪我度过一百多个日夜,更不知道将来的将来,我在这里,而你在哪……哪一季飘飞的柳絮窗外飘来了纷飞的柳絮,久远的思念在心头涌起,相同的场景,却拥着不一样的感怀,时光已苍老,而散不开的记忆每到这个季节,依旧缭绕在心头,无法排解。也许是情感依然纠结,也许是不……夏天最棒的享受小学生作文400字太阳火伞高照,好像撒了许多金粉在大地上,这时,爱美的花朵家族纷纷跑到大树下乘凉,向太阳低头。夏日炎炎,我像院子里的花朵一样,急速的跑到空调室避暑,这时爸爸像大声公般大声的……坚守20年,曾7夺中国第一的国际青年旅舍宣布回归作为联合国教科文组织成员,成立于1932年,总部位于英国的国际青年旅舍联盟(HostellingInternational),在全球80多个国家拥有数万家青年旅舍(Intern……社区最美家庭事迹材料范文通过讲述最美家庭的故事,展示中国妇女在社会生活和家庭生活中的独特作用,彰显出我们这个时代的家风新面貌。下面是语文迷为大家提供的最美家庭的事迹材料范文,供大家参考选择。社区……魔幻之都波哥大波哥大地处安第斯山脉苏马帕斯高原的谷地上,气候宜人。在拉丁美洲常驻的第4个年头,我终于解锁了南美洲沿太平洋地区的最后一个国家哥伦比亚。提起哥伦比亚(Colombia),很……2015中考作文预测握手阅读下面材料,按要求作文。有一则文坛轶闻说,俄罗斯文豪屠格涅夫一日在镇上散步,路边一个乞丐伸手向他讨钱。他很想有所施予,从口袋掏钱时才知道没有带钱袋,见那乞丐的手举得高高……皮肤湿疹出油多?是湿气太重了!6月一定要多喝这碗祛湿神汤,安摘要:夏季祛湿,这碗汤不容错过!芒种一过,雨水逐渐丰沛,加上高温蕴蒸,不少人出现头昏困重、皮肤出油、皮疹增多的问题。这是湿气太重了!湿邪可怕在哪?不论是……送给妈妈的礼物每年的母亲节我都要给妈妈一点小小的惊喜今年也不例外。今年的母亲节正好是新期天,我早早的就从床上跳起来了。因为今天我要当一回lsquo;lsquo;大厨rsquo;rsquo;,……暑假生活下冰雹ldquo;冰雹rdquo;想必大家一定非常熟悉吧!几天前,还下过一场非常大的冰雹雨那。有一天,我在教室里看书,突然,天不知道怎么了,忽然变了脸,不是刮风就是打雷,下雨,……介于天堂和地狱之间的蒙克新博物馆挪威奥斯陆蒙克新博物馆我们不仅仅有《呐喊》!如果说挪威在世界范围外最著名的画作要数蒙克的《呐喊》,那么挪威人正在发出呐喊,宣告蒙克在挪威留下的遗产丰富得多。不……夜阑听风品学网专稿未经允许不得转载卧在孤床,聆听风响,眼前又是一片无尽的寒光,本是人间静谧时,却又不禁想起,放翁那孤床在卧,悲凉中又透出那爱国情怀的《十一月四日风雨大作》:僵卧孤……
75岁之后,还能做好这几件事,一般都会长寿前言:75岁之后的生活并不是我们想得那么简单,做好该做的事情生活才是最主要的。在这个时候,如果我们还不能够明白活着的意义,日子就会过得很辛苦,其实人到75岁,有很多事情我……这4种食物,在吃之前最好先焯水!为了健康,别嫌麻烦焯水看似简单,其实很重要。毒豆、马齿苋事件时有发生,在过去,人们不知道怎样焯水,但是当吃很多食物时都会用开水烫一下,这就是俗语中的冒。但这与焯水的意思相同,可见老百姓的智慧有多……写给山里孩子的一封信400字亲爱的同学:你好!我很希望和你们交朋友,我的家在美丽的杭州,杭州的西湖是天下第一明珠。杭州风景如画,四季分明。美丽的春天,在西湖边,杨柳抽出嫩绿的枝条,桃花咧开粉嘟……为学杯A组中国梦我的梦每个人都有自己伟大梦想,比如说:厨师、老师、医生、作者hellip;而我有一个美丽而璀璨的梦想,就是长大了当一个自由快乐的画家,我知道,有些画家是靠画赚钱的,有些画家小小……我心目中的环卫工人作文范文环卫工人的小学作文篇一:在繁华的城市中,当然少不了这些忙碌的活灵小精灵环卫工人。虽然在许多人的眼里,环卫工人是不起眼的,但是,在我心目中的环卫工人是勤劳的。清早,你准会看……云南在建设铁路4条,拟计划建设20条,你最期待哪一条?说起云南的铁路建设,在全国来说,并不领先,当然也不算落后,截止目前已开通了沪昆高铁、云桂铁路、昆楚大铁路、大丽铁路、大临铁路、中老铁路等,开行动车组的铁路里程已超2000公里。……关于新年的作文迎新年,百姓乐!关于新年的作文:迎新年,百姓乐!寒暑交送,万象更新,一瞬间岁月的年龄在不经意中又多划了一个圈圈,辞旧迎新的时刻,冬姑娘带着吉祥的雪花,然后穿上美丽的银装以崭新的面貌迈着轻……垃圾分类,从我做起二年级作文400字暑假里,学校发布了保护环境,垃圾分类的倡导。让我们从自身做起,垃圾分一分,净化环境。首先,妈妈给我播放了垃圾分类动画片,通过动画片的观看,我知道了垃圾分为:可回收垃圾、有……文案适合假期旅游时发01hr你只管出发,其他的交给天意。02hr别处生活的烟火气。03hr往哪走,都是往前走。04hr总会相逢的,就像山川河流,就像万河归海。05hr哪里有……2016年中考语文作文预测渐至佳境【题目预测】ldquo;渐至佳境rdquo;比喻兴味逐渐浓厚或境况逐渐好转。知识越学越有趣,乐曲越弹越流畅,风光越赏越美妙,作品越读越精彩,与人相处越来越和谐,对镜微笑越……期待作文800字期待,简单的词组,但代表的意义却格外重大。mdash;mdash;题记期待自己的梦想成真,期待想要的玩具降临,期待喜爱的电视剧出来下一集,期待hellip;hell……俄罗斯与西方决裂后,会如何转向中国?除了卖原油,还带一份大礼自从俄乌冲突爆发后,欧美一些国家便对俄罗斯进行严厉的经济制裁,试图以此彻底削弱俄罗斯的实力,进而将其击溃。虽然俄罗斯在这次经济制裁中遭遇重创,但是它也以同样的方式予以回击……
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网