vue复习

发布于:2025-03-31 ⋅ 阅读:(23) ⋅ 点赞:(0)

diff算法

snabbdom:

h函数:产生虚拟节点

第一个参数:为标签,第二个:属性 ,第三个:值

一个虚拟dom的属性:让虚拟节点上树,即生成真实dom

//h函数


//vnode:把参数返回成一个对象

export default function(sel,data,children,text,elm){
    const key=data.key
    return {sel,data,children,text,elm}
}

import vnode from './vnode.js'


//低配版本的diff,必须接受三个参数
// h('div',{},'文字'/[]/h{})

export default function h(a,b,c){
    if(arguments.length<3){
       return ;
    }
    if(typeof c =='string'||typeof c=='number'){
        return vnode(a,b,undefined,c,undefined)
    }

    if(Array.isArray(c)){
        let children=[]
        for(let i=0;i<c.length;i++){
            if(!(typeof c[i]=='object'&& c[i].hasOwnProperty(sel))){
                return 
            }
            children.push(c[i])
        }
        return vnode(a,b,children,undefined,undefined)
    }
    if(typeof c=='object' &&c.hasOwnProperty(sel)){
        let children=[c]
        return vnode(a,b,children,undefined,undefined)
        
    }else{
        return 
    }
    
    
    
}

h('div',{},'文字')

diff算法:

//patch函数:

过程:

先判断老节点是否为虚拟节点,若不是,把它转化为虚拟节点,若是,则判断旧vnode和新的vnode是否为同一节点,若是进行精细比较,若不是,则直接暴力删除添加

(1):如何定义 是相同节点:

        新旧节点的key相同和新旧节点的选择器相同

(2):暴力删除旧的,插入新节点

        创建子节点时,递归创建

        

const myvnode1=h('h1',{},'你好')
const container=document.getElementById('container')

function patch(oldvnode,newnode){
    if(oldnode.sel==''||oldnode.sel=='undefioned'){
        oldvonde=vnode(oldvnode.tagname.toLowerCase(),{},[],undefined,oldvnode)

    }
    if(oldvnode.key==newvnode.key&&oldvnode.sel===newvnode.sel){
        //判断新旧是否为一个对象
       patchVnode(oldVnode,newvnode)
    }else{
    
        let newdom=createElement(newvnode)
        //插入
        oldVonde.elm.parentNode.insertBefore(newdom,oldvnode.elm)
        oldvnode.ele.parentNode.removeChild(oldvnode);
    }
}


function patchvnode(oldvnode,newvnode){

     if(oldvnode==newvnode) return 
        if(newvnode.text!=='undefined' &&newvnode.children.length==0){
            if(newvnode.text!=oldvnode.text){
                oldvnode.elm.innerText=newvnode.text
            }
             
        }else{
            //判断老的有没有children
            if(oldvnode.children!=='undefined'&&oldvnode.children.length!==0){
                 
                updateChilden(oldvnode.elm,oldvnode.children,newvnode.children)
               
            }else{
                //老的没有,新的有
                oldvnode.elm.innerHTML=''
                for(let i=0;i<newvnode.chileren.length;i++){
                    let dom=createElement(newvnode.children[i])
                    oldvnode.ele.appChildren(dom)
                }
            }

            
        }
}


function createElement(vnode){
    //创建dom
    let domnode=document.createElement(vnode.sel)
    if(vnode.text!=''&&(vnode,children=='undefined)){
        domNode.innerText=vnode.text;
        
        
    }else if(Array.isArray(vnode.children)&&vnode.children.length>0){
        //内部是子节点,要进行递归
        for(let i=0;i<vnode.children.length;i++){
            let ch=vnode.childrfen[i]
            let chdom=createElement(ch)
            domnode.appendChild(chdom)
            
            
        }
        
    }
    vnode.elm=domnode
   return vnode.elm

}

function updateChilden(parentelm,oldch,newch){
    let oldstart=0;
    let newstart=0;
    let oldend=oldch.length-1;
    let newend=newch.length-1;
    let oldsnode=oldch[0]
    let oldenode=old[oldend]
    let newsnode=newch[0]
    let newenode=newch[newend]

    while(oldstart<=oldend&&newstart<=newend){
        if(checksamenode(oldsnode,newsnode)){
            patchvnode(oldsnode,newsnode)
            oldsnode=oldch[++oldstart]
            newsnode=newch[++newstart]
            
        }
        //新后和旧后
        else if(checksamenode(oldenode,newenode)){
            patchvnode(oldenode,newenode)
            oldenode=oldch[--oldend]
            newenode=newch[--newend]
        }else if(checksamenode(oldsnode,newenode)){
            patchvnode(oldsnode,newenode)

            parentelm.insertBefore(oldsnode.elm,oldenode.elm.nextSibling)
            oldsnode=oldch[++oldstart]
            newenode=newch[--newend]
        }else if(checksamenode(oldenode,newsnode)){
            patchvnode(oldenode,newsnode)
            parentelm.insertBefore(oldenode.elm,oldsnode.elm)
            oldenode=[--oldend]
            newsnode=[++newstart]
            
        }else{
           
        }
    }
     //
    剩余节点
    if(newstart<=newend){
         for(let i=newstart,i<=newend;i++){
                parentelm.insertBefore(createElement(newch[i]),newch[i+1].elm)
            }
    }else if(oldstart<oldend){
        for(let i=oldsrart,i<=oldend;i++){
            parentelm.removeChild(oldch[i])
        }
        
    }

}

function checksamenode(a,b){
    return a.sel==b.sel&&a.key==b.key
}

diff算法优化:

虚拟dom变为真实dom


网站公告

今日签到

点亮在社区的每一天
去签到