虚拟Dom

Virtual Dom

  • vdom 是vue和react的核心
  • vdom是什么东西,有什么用,为什么会存在vdom?
  • vdom如何应用,核心API是什么?
  • diff算法

## 什么是vdom ##

  • 用js模拟DOM结构
  • DOM变化的对比,放在JS层来做
  • 提高重绘性能
 
  • Item 1
  • Item 2

用js来模拟

 {
   tag:"ul",
   attrs:{
     id:"list"
   },
   children:[
    {
       tag:"li",
       attrs:{ className: "item"},  //class是js的保留字,所以用className
       children:['Item 1']  
    },{
       tag:"li",
       attrs:{ className: "item"},
       children:['Item 2']  
      }
    ]
 }

设计一个需求场景,渲染一个数组成表格

 //Jquery的实现
 
    
    
        
        
        
        Document
        
        
    
    
        

上述办法遇到的问题

    • js原生或者是Jquery框架时代,都是直接操作DOM节点来进行渲染页面,可是这样的代价确实是很大,需要将原本的DOM全部清除,然后在重新渲染一遍
    • 操作Dom非常昂贵。每个Dom自带了太多的属性。 js运行效率高
    • 尽量减少Dom操作
    • 项目越复杂,运行效率越低,影响越严重
    • vdom 可以解决这个问题,将Dom操作方在Js层,提高效率

    vdom如何应用,核心API

    • snabbdom
      为什么是snabbdom.js
      由于虚拟dom有那么多的好处而且现代前端框架中react和vue均不同程度的使用了虚拟dom的技术,因此通过一个简单的 库赖学习虚拟dom技术就十分必要了,至于为什么会选择snabbdom.js这个库呢?原因主要有两个:

      源码简短,总体代码行数不超过500行。
      著名的vue的虚拟dom实现也是参考了snabbdom.js的实现。

      • 用snabbdomjs 实现上述例子
    
    
    
        
        
        
        Document
        
        
        
        
        
        
    
    
    
        

    //修改数据只是修改了 第二个item 第三,第一个数据没变化(F12查看Element 第一个item没有闪烁)

    diff算法

    • 什么是diff算法
    • 去繁就简
    • vdom 为何用diff算法
    • diff算法的实现流程

    diff命令是linux系统自带的基础命令
    git diff 判断文本文件哪里被修改了
    diff算法一直都在,并不是因为react、vue才出现的

    vdom为何使用diff算法

    • DOM 操作是昂贵的,因此尽量减少DOM操作
    • 找出本次DOM必须更新的节点来更新,其他的不更新
    • 这个找出的过程,就需要diff算法

    diff实现过程

    只需要明白

    • path(container,vnode)
    • path(vnode,newnode)

    通过VNode创建一个真实的DOM的流程

      function createElement(vnode){
       var tag= vnode.tag
       var attrs = vnode.attrs||{}
       var children = vnode.children || []
       if(!tag){
           return null
       }
       var elem = document.createElement(tag)
        var attrName 
        for(attrName in attrs){
         if(attrs.hasOwnProperty(attrName)){
            elem.setAttribute(attrName,attrs[attrName])
          }
        }
    
        children.forEach(childNode => {
            elem.appendChild(createElement(childNode))
        });
        //返回真实的Dom
        return elem
    }
    
    

    path(vnode,newVnode) 的实现,

    function updateChildren(vnode,newVnode){
         var children = vnode.children || []
         var newChildren = newVnode.children || []
        
         //遍历现有的children
         children.forEach((child,index )=> {
             var newChild = newChildren[index]
             if(newChild == null){
                return
             }
    
             if(child.tag === newChild.tag){
                  updateChildren(child,newChild)
             }else{
                 replaceNode(child,newChild)
             }
         });
    }
    
    function replaceNode(vnode,newVnode){
        var elem = vnode.elem
        var newElem = createElement(newVnode)
    }
    

    不仅仅是以上的内容,还有以下的内容

    • 节点新增和删除
    • 节点重新排序
    • 节点属性、样式、事件绑定

    你可能感兴趣的:(javascript)