daily-share icon indicating copy to clipboard operation
daily-share copied to clipboard

虚拟dom的实现方式(2020-2-18)

Open yaogengzhu opened this issue 5 years ago • 1 comments

虚拟dom的实现方式

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 setAttr(node, key, value) {
    // eslint-disable-next-line default-case
    switch(key) {
        case 'value' :  // node是不是一个input或者是textarea
            if (node.tagName.toUpperCase() === 'INPUT' || node.tagName.toUpperCase() === 'TEXTAREA') {
                node.value = value
            } else {
                node.setAttribute(key, value)
            }
            break
        case 'style' : 
            node.style.cssText = value
            break
        default : 
            node.setAttribute(key, value)
    }
}
 
// 将虚拟dom专成真实dom
function render(eleObj) {
    const el = document.createElement(eleObj.type)
    // 给元素设置属性
    for (let key in eleObj.props) {
        setAttr(el, key, eleObj.props[key])
    }
    // 遍历子元素,是虚拟dom继续渲染
    eleObj.children.forEach( child => {
        // 判断child是否是元素,还是文本
        child = (child instanceof Element) ? render(child) : document.createTextNode(child)
        el.appendChild(child)
    })
    
    return el
}

// 将虚拟dom转化成真实dom进行渲染
function renderDom(el, target) {
    target.appendChild(el)
}

export {
    createElement,
    render,
    Element,
    renderDom
}

yaogengzhu avatar Feb 18 '20 14:02 yaogengzhu

import { createElement, render } from './diff'
let virtualDom = createElement('ul', { calss: 'list'}, [
    createElement('li', { class: 'item'}, ['a']),
    createElement('li', { class: 'item'}, ['b']),
    createElement('li', { class: 'item'}, ['c'])
])

const el = render(virtualDom)
console.log(el)
console.log(virtualDom)

yaogengzhu avatar Feb 18 '20 14:02 yaogengzhu