手写虚拟dom转真实dom


/**
* vnode转化成真实DOM,实现思路
* 1. render函数,render(vnode, container)
* 2. createDom,根据参数创建对应的标签
* 3. 根据属性,新建还是更新,如果有children,则递归render
* 4. 更新属性:style, 则更改style上的attr,其他类型,则是修改对象上的属性
*/
// 虚拟dom转真实dom
const vnode = {
  tag: 'div',
  attrs: {
     id: 'app',
  },
  children: [{
      tag: 'span',
      children: [{
      tag: 'a',
      children: [],
  }],
  },
  {
    tag: 'span',
    children: [{
       tag: 'a',
       children: [],
        },
        {
          tag: 'a',
          children: [],
        },
    ],
 },
 ],
}
render(vnode, document.querySelector('#root'))

function render(vnode, container){
let dom = createDom(vnode)
container.appendChild(dom)
}
function createDom(vnode){
// 节点上有啥属性?
   const {tag, attrs, children} = vnode
let dom = document.createElement(tag)

if(typeof attrs === 'object'){
updateProps(dom, {}, attrs)
}

if(children.length > 0){
  reconcilrChildren(children, dom)
}
  return dom
}

function reconcilrChildren(childrenDom, parentDom){
  for(let i = 0; i < childrenDom.length; i++){
  render(childrenDom[i], parentDom)
  }
}

function updateProps(dom, oldprops = {}, newProps = {}){
  for(const key in newProps){
  // 新的属性,直接赋值
  if(key === 'style'){
    // style
    let styleObj = newProps[key]
    for(let attr in styleObj){
    dom.style[attr] = styleObj[attr]
    }
    }else {
    dom[key] = newProps[key]
    }
  }

  // 老的属性,需要删除
   for(let key in oldprops){
    // 如果在新的属性中不存在老的属性,则删除
    if(!newProps.hasOwnProperty(key)){
    delete dom[key]
    }
  }
}
posted @ 2023-01-04 00:51  yiyunh  阅读(215)  评论(0)    收藏  举报