We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
本文主要参考了从零开始实现一个React和从 0 到 1 实现React 工作中经常使用react,对于react中的一些虚拟DOM、生命周期、组件等概念知其然,不知其所以然。虽然知道这些怎么用的就足够应付大部分的工作,但是作为一个开发者,还是要有追求的。所以有了这个系列,一步一步实现一个简单的react出来。
react
DOM
我们平时在react中写的JSX,其实是一种语法糖,会被babel转换成React.createElement()。我们可以在babel官网上做个实验,看下JSX会被babel转换成什么。下面是个简单的例子。
JSX
babel
React.createElement()
我们可以看到,JSX会被转成React.createElement(tag, attrs, child1, child2, ...)这种形式。那我们只要装个babel插件,然后写个createElement方法就可以处理JSX代码了。
React.createElement(tag, attrs, child1, child2, ...)
createElement
首先安装babel模块,babel的.babelrc配置如下:
.babelrc
{ "presets": ["env"], "plugins": [ [ "transform-react-jsx", { "pragma": "React.createElement" } ] ] }
使用打包工具parcel,webpack也可以。比较懒,使用了parcel来打包代码。
parcel,webpack
上面我们已经提到了JSX会被babel转换为React.createElement(tag, attrs, child1, child2, ...)。 第一个参数:是元素的标签名,可以是div、span等。 第二个参数:是元素的属性名,可以是className、onClick等。 之后的参数,是元素的子节点。 所以我们实现一个函数createElement,接受上面的参数,然后将这些参数返回就可以了。
div、span
className
onClick
const createElement = (tag, attrs, ...childs) => { return { tag, attrs, childs } }
看下效果如何。
const React = { createElement } const title = ( <div className="title"> <p>Hello, world!</p> </div> ) console.log(title)
打开Chrome的控制台,我们可以看到差不多是我们想要的。
createElement方法返回的对象就是虚拟DOM,这个对象中记录了该DOM节点的所有信息,根据这些信息我们可以将虚拟DOM转化为真实的DOM。
在react中,将vdom渲染成真实的DOM,我们使用的是ReactDOM.render,像这样。
ReactDOM.render( <div>Hello, world!</div>, // 这个会被转化为vdom document.getElementById('root') // 获取根节点 )
我们可以看出,render实现的功能是将vdom转化为真实的dom,挂载到根节点上。明白这一点,代码就很好写了。
render
vdom
dom
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, attr, value) => { if (attr === "className") { attr = "class" } // 处理事件 if (/on\w+/.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) } }
在react中,jsx会被babel转化为React.createElement(标签、属性、子元素1、子元素2、...)形式,该函数返回一个对象,即虚拟dom。然后ReactDOM.render(),会将虚拟dom转化为真实的dom。 附上本文代码地址
jsx
React.createElement(标签、属性、子元素1、子元素2、...)
ReactDOM.render()
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
本文主要参考了从零开始实现一个React和从 0 到 1 实现React
工作中经常使用
react
,对于react
中的一些虚拟DOM
、生命周期、组件等概念知其然,不知其所以然。虽然知道这些怎么用的就足够应付大部分的工作,但是作为一个开发者,还是要有追求的。所以有了这个系列,一步一步实现一个简单的react
出来。语法糖JSX
我们平时在
react
中写的JSX
,其实是一种语法糖,会被babel
转换成React.createElement()
。我们可以在babel官网上做个实验,看下JSX
会被babel
转换成什么。下面是个简单的例子。我们可以看到,
JSX
会被转成React.createElement(tag, attrs, child1, child2, ...)
这种形式。那我们只要装个babel
插件,然后写个createElement
方法就可以处理JSX
代码了。createElement方法和虚拟DOM
准备
首先安装
babel
模块,babel
的.babelrc
配置如下:使用打包工具
parcel,webpack
也可以。比较懒,使用了parcel来打包代码。实现
上面我们已经提到了
JSX
会被babel
转换为React.createElement(tag, attrs, child1, child2, ...)
。第一个参数:是元素的标签名,可以是
div、span
等。第二个参数:是元素的属性名,可以是
className
、onClick
等。之后的参数,是元素的子节点。
所以我们实现一个函数
createElement
,接受上面的参数,然后将这些参数返回就可以了。看下效果如何。
打开Chrome的控制台,我们可以看到差不多是我们想要的。
createElement
方法返回的对象就是虚拟DOM
,这个对象中记录了该DOM
节点的所有信息,根据这些信息我们可以将虚拟DOM
转化为真实的DOM
。将虚拟DOM渲染成真实DOM
在react中,将vdom渲染成真实的DOM,我们使用的是ReactDOM.render,像这样。
我们可以看出,
render
实现的功能是将vdom
转化为真实的dom
,挂载到根节点上。明白这一点,代码就很好写了。这样我们就将虚拟dom渲染成真实的dom,考虑到热更新,我们需要在render之前先清除下root节点下的内容。
总结
在
react
中,jsx
会被babel
转化为React.createElement(标签、属性、子元素1、子元素2、...)
形式,该函数返回一个对象,即虚拟dom
。然后ReactDOM.render()
,会将虚拟dom
转化为真实的dom
。附上本文代码地址
The text was updated successfully, but these errors were encountered: