首页 > 其他 > 详细

Diff

时间:2020-05-21 22:53:32      阅读:46      评论:0      收藏:0      [点我收藏+]
class Element{
    constructor(type, props, children) {
        this.type = type
        this.props = props
        this.children = children
    }
}

function createElement (type, props, children) {
    return new Element(type, props, children)
}

function render(node) {
    let el = document.createElement(node.type)
    for(let key in node.props) {
        setAttr(el, key, node.props[key])
    }
    node.children.forEach(child=>{
        child = (child instanceof Element) ? render(child) : document.createTextNode(child)
        el.appendChild(child)
    })
    return el
}

function setAttr(node, key, value) {
    switch (key) {
        case ‘value‘:
            if(node.tagName.toLowerCase()===‘input‘||node.tagName.toLowerCase()===‘textarea‘) {
                node.value = value
            } else {
                node.setAttribute(key, value)
            }
            break;
        case ‘style‘:
            node.style.cssText = value
            break;
        default:
            node.setAttribute(key, value)
            break;
    }
}

function renderDom(el, target) {
    target.appendChild(el)
}

function diff(oldNode, newNode) {
    let patches = {}
    walk(oldNode, newNode, 0, patches)
    return patches
}

function walk(oldNode, newNode, index, patches) {
    let current = []
    if(!newNode) {
        current.push({type:‘REMOVE‘,index})
    } else if(isString(oldNode)&&isString(newNode)) {
        if(oldNode!==newNode) {
            current.push({type:‘TEXT‘,text:newNode})
        }
    } else if(oldNode.type === newNode.type) {
        let attr = diffAttr(oldNode.props, newNode.props)
        if(Object.keys(attr).length>0) current.push({type:‘ATTR‘,attr})
        oldNode.children.forEach((child, index)=>{
            diffChildren(child, newNode.children[index], patches)
        })
    } else {
        current.push({type:‘REPLAY‘,newNode})
    }
    if(current.length>0) {
        patches[index]=current
    }
}

function isString(node) {
    return typeof node === ‘string‘
}

function diffAttr(oldNode, newNode, patches) {
    let attr = {}
    for(let key in oldNode) {
        if(oldNode[key] !== newNode[key])
            attr[key] = newNode[key]
    }

    for(let key in newNode) {
        if(!oldNode.hasOwnProperty(key))
            attr[key] = newNode[key]
    }
    return attr
}
let num = 0
function diffChildren(oldNode, newNode, patches) {
    walk(oldNode, newNode, ++num, patches)
}

let allPatches
let patchIndex = 0
// 这里的node应该是一个真实的Dom对象
function patch(node, patches) {
    allPatches = patches
    patchWalk(node)
}

function patchWalk(node) {
    let current = allPatches[patchIndex++]
    let childNodes = node.childNodes
    if(current) {
        doPatch(node, current)
    }
    childNodes.forEach(child=>patchWalk(child))
}

function doPatch(node, patches) {
    patches.forEach(patch=>{
        switch (patch.type) {
            case ‘ATTR‘:
                for(let key in patch.attr) {
                    let value = patch.attr[key]
                    if(value) {
                        node.setAttribute(key, value)
                    } else {
                        node.removeAttribute(key)
                    }
                }
                break;
            case ‘TEXT‘:
                node.textContent = patch.text
                break;
            case ‘REPLAY‘:
                let newNode = pathc.newNode
                node.parentNode.replaceChild(newNode,node)
                break;
            case ‘REMOVE‘:
                node.parentNode.removeChild(node)
            default:
                break;
        }
    })
}


Diff

原文:https://www.cnblogs.com/lbzli/p/12933793.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!