虚拟dom

vue中的虚拟dom

简介

首先vue会把模板编译成render函数,运行render函数生成虚拟dom

虚拟dom通过 diff算法 对比差异 渲染不同的部分 然后更新视图

为什么会需要虚拟dom

在主流框架 Angular , Vue.js (1.0)React 中都有一个共同点,那就是它们都不知道哪些状态(state)变了。因此就需要进行比对,在React中使用的虚拟dom比对, Angular 中使用的是脏检查的流程

而在 Vue.js中使用的是变化侦测的方式,它在一定程度上知道具体哪些状态发生了变化,这样就可以通过更细粒度的绑定来更新视图。也就是说,在Vue.js中,当状态发生变化时,它在一定程度上知道哪些节点使用了这个状态,从而对这些节点进行更新操作,根本不需要比对

但是这样做的代价就是,粒度太细,每一个都有对应的 watcher 来观察状态变化,这样就会浪费一些内存开销,绑定的越多开销越大,如果这运用在一个大型项目中,那么他的开销无疑是非常大的

因此从 Vue.js 2.0 开始借鉴 React 中的虚拟DOM ,组件级别是一个watcher实例,就是说即便一个组件内有10个节点使用了某个状态,但其实也只有一个watcher在观察这个状态的变化。

什么是虚拟dom

虚拟DOM是通过状态生成一个虚拟节点树(vnode) ,然后使用虚拟节点树进行渲染。 在渲染之前,会使用新生成的虚拟节点树和上一次生成的虚拟节点树进行对比 (diff算法) ,只渲染不同的部分

虚拟节点树其实是由组件树建立起来的整个虚拟节点(Virtual Node,也经常简写为vnode)树

在Vue.js中,我们使用模板来描述状态DOM之间的映射关系。Vue.js通过编译将模板转换成渲染函数(render),执行渲染函数就可以得到一个虚拟节点树,使用这个虚拟节点树就可以渲染页面

模板编译成render函数

将模板编译成渲染函数可以分两个步骤,先将模板解析成AST(Abstract Syntax Tree,抽象语法树),然后再使用AST生成渲染函数。

但是由于静态节点不需要总是重新渲染,所以在生成AST之后、生成渲染函数之前这个阶段,需要做一个操作,那就是遍历一遍AST,给所有静态节点做一个标记,这样在虚拟DOM中更新节点时,如果发现节点有这个标记,就不会重新渲染它。所以,在大体逻辑上,模板编译分三部分内容:

  • 将模板解析为AST
  • 遍历AST标记静态节点
  • 使用AST生成渲染函数

虚拟dom做了什么

虚拟DOM在Vue.js中所做的事情其实并没有想象中那么复杂,它主要做了两件事。

  • 提供与真实DOM节点所对应的虚拟节点vnode。
  • 将虚拟节点vnode和旧虚拟节点oldVnode进行比对,然后更新视图。

对两个虚拟节点对比是虚拟dom 中最核心的算法 (diff),它可以判断出哪些节点发生了变化,从而只对发生了变化的节点进行更新操作

小结

虚拟DOM是将状态映射成视图的众多解决方案中的一种,它的运作原理是使用状态生成虚拟节点,然后使用虚拟节点渲染视图。

为什么什么会需要虚拟dom
框架设计

Vue 和 React 框架设计理念都是基于数据驱动的,当数据发生变化时 就要去更新视图,要想知道在页面众多元素中改动数据的元素 并根据改动后的数据去更新视图 是非常困难的

所以 Vue 和 React 中都会有一个 Render函数 或者类似于Render函数的功能,当数据变化时 全量生成Dom 元素 如果是直接操作 真实Dom 的话 是很昂贵的,就会严重拖累效率,所以就不生成真实的Dom,而是生成虚拟的Dom 当数据变化时就是 对象 和 对象 进行一个对比 ,这样就能知道哪些数据发生了改变 从而去操作改变的数据后的Dom元素

这也是一个 “妥协的结果”

跨平台

现阶段的框架他不仅仅能在浏览器里面使用,在小程序,移动端,或者桌面端也可以使用,但是真实Dom仅仅指的是在浏览器的环境下使用,因此他不能直接生成真实Dom ,所以选择生成一个在任何环境下都能被认识的虚拟Dom 最后根据不同的环境,使用虚拟Dom 去生成界面,从而实现跨平台的作用 --- 一套代码在多端运行

全部评论

相关推荐

bg双非本科,方向是嵌入式。这次秋招一共拿到了 8 个 offer,最高年包 40w,中间也有一段在海康的实习经历,还有几次国家级竞赛。写这篇不是想证明什么,只是想把自己走过的这条路,尽量讲清楚一点,给同样背景的人一个参考。一、我一开始也很迷茫刚决定走嵌入式的时候,其实并没有一个特别清晰的规划。网上的信息很零散,有人说一定要懂底层,有人说项目更重要,也有人建议直接转方向。很多时候都是在怀疑:1.自己这种背景到底有没有机会2.现在学的东西到底有没有用3.是不是已经开始晚了这些问题,我当时一个都没答案。二、现在回头看,我主要做对了这几件事第一,方向尽早确定,但不把自己锁死。我比较早就确定了嵌入式这个大方向,但具体做哪一块,是在项目、竞赛和实习中慢慢调整的,而不是一开始就给自己下结论。第二,用项目和竞赛去“证明能力”,而不是堆技术名词。我不会刻意追求学得多全面,而是确保自己参与的每个项目,都能讲清楚:我负责了什么、遇到了什么问题、最后是怎么解决的。第三,尽早接触真实的工程环境。在海康实习的那段时间,对我触动挺大的。我开始意识到,企业更看重的是代码结构、逻辑清晰度,以及你能不能把事情说清楚,而不只是会不会某个知识点。第四,把秋招当成一个需要长期迭代的过程。简历不是一次写完的,面试表现也不是一次就到位的。我会在每次面试后复盘哪些问题没答好,再针对性补。三、我踩过的一些坑现在看也挺典型的:1.一开始在底层细节上纠结太久,投入产出比不高2.做过项目,但前期不会总结,导致面试表达吃亏3.早期有点害怕面试,准备不充分就去投这些弯路走过之后,才慢慢找到节奏。四、给和我背景相似的人一点建议如果你也是双非,准备走嵌入式,我觉得有几件事挺重要的:1.不用等“准备得差不多了”再投2.项目一定要能讲清楚,而不是做完就算3.不要只盯着技术,多关注表达和逻辑很多时候,差的不是能力,而是呈现方式。五、写在最后这篇总结不是标准答案,只是我个人的一次复盘。后面我会陆续把自己在嵌入式学习、竞赛、实习和秋招中的一些真实经验拆开来讲,希望能对后来的人有点帮助。如果你正好也在这条路上,希望你能少走一点弯路。
x_y_z1:蹲个后续
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务