/**
* 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]
}
}
}
标签:render,dom,tag,vnode,虚拟,key,手写,children
From: https://www.cnblogs.com/yiyunh/p/17023805.html