虚拟DOM与render函数

目录

一、虚拟DOM

1、虚拟DOM是什么

2、为什么要使用虚拟DOM

(1)浏览器显示网页的五步过程:

(2)虚拟DOM的优点

3、Diff算法

二、VNode简介

1、VNode是什么

2、VNode的作用

 3、VNode的优点

4、VNode如何生成:在Vue源码中,VNode是通过一个构造函数生成的。

 VNode的生成过程如下:

 三、render函数

1、初识render函数:

 2、为什么使用render函数

3、render函数的解析

四、实例属性

1、组件树的访问

2、虚拟DOM的访问:

五、实例方法

1、实例DOM方法的使用

2、实例event方法的使用

3、$watch()的使用


一、虚拟DOM

1、虚拟DOM是什么

​ (1) Vue通过建立一个虚拟DOM树对真实DOM发生的变化保持追踪。

​ (2)一棵真实DOM树的渲染需要先解析CSS样式和DOM树,然后将其整合成一棵渲染树,再通过布局算法去计算每个节点在浏览器中的位置,最终输出到显示器上。而虚拟DOM则可以理解为保存了一棵DOM树被渲染前所包含的所有信息,这些信息可以 通过对象的形式一直保存在内存中,并通过javascript的操作进行维护

2、为什么要使用虚拟DOM

(1)浏览器显示网页的五步过程:

​         a、解析标签,生成元素树(DOM树)

        ​ b、解析样式,生成样式树

​         c、生成元素与样式的关系

        ​ d、生成元素的显示坐标

        ​ e、显示页面

若修改真实的DOM元素,那么上述5步将重新走一遍,修改几次就走几遍,性能很差。如果使用虚拟DOM,虚拟DOM存储在内存中,对每个元素的修改是在内存中进行的,修改完后,比较虚拟DOM和真实DOM的差异,当有差异时,再一次过去更新网页的显示,而不是每次都重新按照浏览器的运行过程走。

(2)虚拟DOM的优点

a、保证性能的下限:框架的虚拟DOM需要适应任何上层API可能产生的操作,它的一些DOM操作的实现必须是普适的,所以它的性能并不是最优的,但是比起粗暴的DOM操作性能要好很多,因此框架的虚拟DOM至少可以保证在不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限

b、无须手动操作DOM:只需要编写好View-Model的代码逻辑,框架会根据虚拟DOM和数据双向绑定,以可以预期的方式更新视图,极大的提高开发效率

c、跨平台:虚拟DOM本质是javascript对象,而DOM与平台强相关。相比之下虚拟DOM可以进行更方便地跨平台操作

3、Diff算法

当虚拟DOM发生改变时,为了以最小的性能开销完成更新操作,需要比较新旧虚拟DOM,用于比较的算法称为Diff算法

​ Diff算法本身非常复杂,实现难度很大。常用的核心函数有两个

(1)patch(container,vnode):将虚拟DOM渲染成真正的DOM。即在初次渲染的时候,将虚拟的DOM渲染成真正的DOM,然后插入到容器里面

function createElement(vnode){
    var tag = vnode.tag
    var attrs = vnode.attrs || {}
    var children = vnode.children || []
    if(!tag){
       return null
    }
    //创建真实的DOM元素
    var vm = document.createElement(tag)
    //定义属性
    var attrName
    for(attrName in attrs){
       if(attrs.hasOwnProperty(attrName)){
           vm.setAttribute(attrName,attrs[attrName])
       }
    }
    //定义子元素
    children.forEach(function(childVnode){
       //给vm添加子元素,如果还有子节点,则递归的生成子节点
       vm.appendChild(createElement(childVnode))
    })
    //返回真实的DOM元素
    return  vm
}

(2)patch(vnode,newVnode);再次渲染的时候,将新的VNode和旧的VNode进行对比,然后将之间的差异应用到所构建的真实DOM树上。

function updateChildren(vnode,newVnode){
   var children = vnode.children || []
   var newChildren = newVnode.children || []
   //遍历现有的children
   children.forEach(function(childVnode,index){
      var newChildVnode = newChildren[index]
      if(childVnode.tag === newChildVnode.tag){
         //深层次对比,递归
         updateChildren(childVnode,newChildVnode)
      }else{
         //两者tag不一样,则替换
         replaceNode(childVnode,newChildVnode)
      }
   })
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值