构建虚拟节点并且转化为真实dom

87 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

在上一文我们介绍了一些前期工作,现在我们就开始虚拟节点转化,因为我们没有做模版转化,所以就直接用写好的数据了,

// 这个就是我们用到的数据,把当前数据转化虚拟节点
var vdom = createElement('ul',{class:'list',width:'300px'},[
    createElement('li',{class:'item',"data-index":0},[
        createElement('p',{ class:'text' },['第一个列表'])
    ]),
    createElement('li',{ class: 'item',"data-index":1},[
        createElement('p',{ class:'text' },['第二个列表'])
    ]),
    createElement('li',{ class:'item',"data-item":2 },["第三个列表"])
])
conso.log(vdom)

把上面数据转化为虚拟节点的方式主要是实现createElement可以看下createElement的实现方式 vdom.js

import Element from './Element.js'
function createElement(type,props,children) { // 把这三个转化为对象
  return new Element(type,props,children) // 利用new一个对象的方式把每一条数据独立起来,后续也会其他用处
}

export {
    createElement
}

Element.js

// 新建一个类(也就是构造函数)
function Element(type,props,children) { // 没一个标签都是一个类, 互不影响
  // type 标签 props属性 children子元素
  this.type = type
  this.props = props
  this.children = children
}
export default Element

可以看下目录结构

diff5.png 图片上是我的目录结构

可以看下我的打印的结构

diff6.png 虚拟节点转化完成

下一步虚拟节点转真实dom 需要写一个render函数 大家可以看下

function render(vdom) {
    // 虚拟转真实 我们需要新建html标签
    let { type, props, children} = vdom // 把属性解构出来
    const el = document.createElement(type)
    // 我们需要遍历属性 用 for in
    for (let key in props) { // 直接为新建元素新建属性是不行的 ,
    // 我们需要判断元素区分input节点 textarea节点 剩下的节点就可以setAttrbute
       setAtts(el,key,props[key]) // 判断节点方法   
    }
    // 还需要去判断children
    children.map(c=>{
        // 需要判断c 是否字符串节点 换另外一种思路 
        //非文本我们都是用Element构造函数生成,所以我们可以判断是否是Element
        if (c instanceof Element) {
            c = render(c)
        } else {
            c = document.createTextNode(c)
        }
        el.appendChild(c)
    })
    console.log(el)
    return el
}
function setAtts(el,key,value) { // 属性添加也需要判断
    // 判断属性是否是value
    if (key=='value') {
        if (el.tagName=='INPUT'||el.tagName=="TEXTAREA") {
            el.value = value
        } else {
            el.setAttribute(key,value)
        }
    } else if(key=='style') { // 
        el.style.cssText = value
    } else {
        el.setAttribute(key,value)
    }

}

后面是渲染到页面上

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