一起来玩一个模拟游戏吧:浅谈虚拟DOM
Posted 404 we found
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起来玩一个模拟游戏吧:浅谈虚拟DOM相关的知识,希望对你有一定的参考价值。
出于各种机缘巧合,前端三大主流框架 VAR (Vue、Angular以及React)我选择了React。相对于新晋王者Vue,React上手无疑是相对较难的。但喜欢就是喜欢,也没有那么多理由能够解释为什么...
三大主流框架之受欢迎的原因有很多:数据驱动、组件化思想...等等,在底层方面,最主要的一个原因便是:虚拟DOM
虚拟DOM的诞生,在性能方面使得JQ这种轻量库渐渐被主流框架所替代。虚拟DOM的诞生,使得跨端开发成为可能。
那么,一起来看看这个颠覆性的革命产物吧
要想做到优化,做到性能提升,我们就必须得知道规则、知道底层原理。现在,假设我们不知道React,我们以一个开发者的视角来模拟一下数据驱动+模版语言的渲染过程。(如果不知道浏览器渲染原理可以康康这个 )
1.0 伟大的开始
接触过React的伙伴应该知道,React的程序设计思想是数据驱动,组件之间通过单向数据流进行影响。React中还有一大亮点便是JSX——一中JS的语法拓展,其格式与模板语言相似。
好啦,了解了React的两大特点后,我们就可以开始我们的模拟游戏啦
首先,依照浏览器渲染原理,我们需要 state 状态数据以及 类似于html的 JSX模板。让两者结合生成 DOM 树(这是我们第一次渲染结果)
我们知道,在React中,若 state 状态数据或 props 属性发生改变,都会导致 render 函数的调用从而造成重新渲染。
那么,假设现在 state 被改变了。新的 state 会和 JSX 生成新的 DOM 树。
(最近入手了iPad,真的好好用!别嫌我字丑嗷o(╥﹏╥)o)
(原谅我读书读的少,模板的板老是写错,对不起)
我们让新的DOM树代替覆盖原有的DOM树。如果知道浏览器渲染原理的朋友便会清楚,这是个很糟糕的做法!这也太伤性能了。所以,我们得开始第二种模拟方案:DOM对比。虽然第一种方案很糟糕,但至少我们开始了不是吗?无论多艰难,只要在路上了就好。
2.0 找不同
通过浏览器渲染原理我们可以发现,第一个方案有一个耗性能的地方在于第五步:新生成的真实DOM替换原始的DOM。这么做会导致大量的回流、重绘,重新计算、布局、渲染,这都是非常损耗性能的。
看到这,自然而然地就会想:如果我只是替换不一样的DOM节点呢?真的有必要完全替换成新的节点吗?
所以,诞生了我们的第二种方案:在新的DOM生成,不进行挂载,让它与原始的DOM进行比对,对不同的节点进行局部替换
(对不起,模板的板写错了,这图太难改了就懒得改了。对不起是我态度不端正)
3.0 性能革命
通过方案二,我想我们的性能有了一定的提升,可是这种提升远远不够。我们复盘下前两个方案,发现有一步真的太太太太伤性能了:数据改变后,生成新的DOM树。不论是否采用对比方案,这个新的DOM结构都会由被调用的Web Api生成。不论是调用这种级别的API还是生成新的DOM树这个过程,都是会调用大量资源,对性能进行消费。
那,我们有没有方法对这个过程进行降维处理?生成一个类似DOM结构的玩意?
这便是虚拟DOM的核心思想!用一个JS对象来代替真实的DOM结构!
(对不起,我模板的板写错了)
JSX与虚拟DOM
刚刚一直在说JSX模板,那么JSX原理到底是什么呢?
JSX其实有点像是一个语法糖。它在一定程度上等同于 React.createElement() 这个React内置方法。两者区别在于,React.createElement() 更倾向于底层的React。
举个栗子:
render(){ // 1
return <div>item</div>
}
render(){ // 2
return React.createElement('div',{},item); // {} 是对元素属性的挂载
}
1与2两段代码是完全等效的。
每次编译JSX,其实是会先翻译成 React.createElement() 再进行编译,这也是为什么JSX与state数据结合生成JS对象的底层原理
关于Diff算法
上面解决了生成新的DOM树而造成的性能损耗,接下来来看看React是如何解决虚拟DOM进行比对时的性能损耗
在DOM结构的比对方面,React采用的是Diff算法。
Diff -> Difference
我们知道,虚拟DOM发生变化的先决条件是 setState 导致的 state 数据发生变化。
而对于 setState,React采用了异步处理的方式避免了某个短时间间断内触发多次state数据变化而造成的不必要的虚拟DOM生成及比对。
Diff算法的核心概念在于:同结构层比对,且一旦发现某一层不同,直接对该层及该层以下的所有层进行虚拟DOM替换。
这样比对虽然会造成一定渲染上性能的浪费,可是它靠着此算法的高效性,大幅降低了算法上造成的性能。
虚拟DOM的优点
为什么我会说虚拟DOM是一个颠覆性产物呢?不光光是因为它给性能提升上带来的颠覆,更是因为它对整个开发生态带来的颠覆。
我们知道,DOM是个仅存于浏览器的结构对象。而虚拟DOM,就仅是一个JS对象。也就是说,能有JS出现的地方,虚拟DOM都能存在。所以使得跨端开发成为可能。
道阻且长,Web开发的终点漫漫无期,只希望自己能在这条路上,守得初心且坚定不移。
豁然想起一位Web前辈的话:JS,能写一切。
这句话虽然有些夸张,但不失一抹豪情。心怀不羁,勇往直前。我想,这是JS教给我的一种道吧。
以上是关于一起来玩一个模拟游戏吧:浅谈虚拟DOM的主要内容,如果未能解决你的问题,请参考以下文章
一起来学pygame吧 游戏开发30例——接盘侠 小游戏 丨蓄力计划