搭建环境与JSX&虚拟DOM

使用parcel打包

npm install parcel-bundler 打包命令 npx parcel index.html

安***abel插件

"babel-plugin-transform-react-jsx": "^6.24.1", //主要调用React.createElement方法将jsx转换为数组
"babel-preset-env": "^1.7.0",
"babel-core": "^6.26.3",
"parcel-bundler": "^1.12.3"

//index.html
<body>
    <div id="root"></div>
    <script src="./index.js"></script>
</body>
//index.js
import React from './react'
import ReactDom from './react-dom'
const ele = (
    <div className='active' title='123'>
        hello,<span>react</span>
    </div>
)
ReactDom.render(ele, document.querySelector('#root'))

/react/index.js

/**
 * createElement(tag,attrs,child1,child2)
 */
const React = {
    createElement
}
function createElement(tag, attrs, ...childrens) {
    return {
        tag,
        attrs,
        childrens
    }
}
export default React

/react-dom/index.js

const ReactDom = {
    render
}
function render(vnode, container) {
    if (vnode === undefined) {
        return
    }
    if (typeof vnode === 'string') {
        //创建文本节点
        const textNode = document.createTextNode(vnode)
        return container.appendChild(textNode)
    }
    //虚拟dom
    const { tag, attrs, childrens } = vnode
    const dom = document.createElement(tag)
    if (attrs) {
        //遍历
        Object.keys(attrs).forEach(key => {
            const value = attrs[key]
            setAttribute(dom, key, value)
        })
    }
    //遍历子节点
    childrens.forEach(child => {
        render(child, dom)
    })
    return container.appendChild(dom)
}
//设置属性
function setAttribute(dom, key, value) {
    //将className转换成class
    if (key === 'className') {
        key = 'class'
    }
    //如果是事件 onClick onBlur...
    if (/on\w+/.test(key)) {
        key = key.toLowerCase()
        dom[key] = value || ''
    } else if (key === 'style') {
        if (!value || typeof value === 'string') {
            dom.style.cssText = value
        } else if (value && typeof value === 'object') {
            //{width:20}
            for (let k in value) {
                if (typeof value[k] === 'number') {
                    dom.style[key] = value[k] + 'px'
                } else {
                    dom.style[key] = value[k]
                }
            }
        }
    }
    else {
        //其他属性
        if (key in dom) {
            dom[key] = value || ''
        }
        if (value) {
            dom.setAttribute(key, value)
        } else {
            dom.removeAttribute(key)
        }
    }
}
export default ReactDom