搭建环境与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