实现一个react系列一:JSX和虚拟DOM
前言工作中经常使用 语法糖JSX我们平时在 我们可以看到, createElement方法和虚拟DOM
{ "presets": ["env"],"plugins": [ [ "transform-react-jsx",{ "pragma": "React.createElement" } ] ] } 使用打包工具
const createElement = (tag,...childs) => { return { tag,childs } } 看下效果如何。 const React = { createElement } const title = ( <div className="title"> <p>Hello,world!</p> </div> ) console.log(title) 打开Chrome的控制台,我们可以看到差不多是我们想要的。 createElement 方法返回的对象就是虚拟DOM ,这个对象中记录了该DOM 节点的所有信息,根据这些信息我们可以将虚拟DOM 转化为真实的DOM 。
将虚拟DOM渲染成真实DOM在react中,将vdom渲染成真实的DOM,我们使用的是ReactDOM.render,像这样。 ReactDOM.render( <div>Hello,world!</div>,// 这个会被转化为vdom document.getElementById('root') // 获取根节点 ) 我们可以看出, const ReactDom = { render } // 将 vdom 转换为真实 dom const render = (vdom,root) => { if (typeof vdom === "string") { // 子元素如果是字符串,直接拼接字符串 root.innerText += vdom return } const dom = document.createElement(vdom.tag) if (vdom.attrs) { for (let attr in vdom.attrs) { const value = vdom.attrs[attr] setAttribute(dom,attr,value) } } // 遍历子节点 vdom.childs.forEach(child => render(child,dom)) // 将子元素挂载到其真实 DOM 的父元素上 root.appendChild(dom) } // 设置 dom 节点属性 const setAttribute = (dom,value) => { if (attr === "className") { attr = "class" } // 处理事件 if (/onw+/.test(attr)) { attr = attr.toLowerCase() dom[attr] = value || "" } else if (attr === "style" && value) { // 处理 style 样式,可以是个字符串或者对象 if (typeof value === "string") { dom.style.cssText = value } else if (typeof value === "object") { for (let styleName in value) { dom.style[styleName] = typeof value[styleName] === "number" ? value[styleName] + "px" : value[styleName] } } } else { // 其他属性 dom.setAttribute(attr,value) } } 这样我们就将虚拟dom渲染成真实的dom,考虑到热更新,我们需要在render之前先清除下root节点下的内容。 const ReactDOM = { render: (vdom,root) => { root.innerText = "" render(vdom,root) } } 总结在 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |