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 在上一节JSX和虚拟DOM中,我们了解了react中的JSX到虚拟dom,以及如何将虚拟dom渲染成真实的dom。在这一节中,我们将会了解react中组件是如何渲染的。
react
JSX
dom
在react中,组件有两种使用方法:
import React from 'react' // 类定义的组件 class Hello extends React.Component { render() { return <div>hello</div> } } // 无状态组件,通过函数来定义 const World = () => { return <h1>world!</h1> } ReactDom.render(<Hello />, document.getElementById('#root'))
通过类定义组件时,是需要继承React.component的,我们第一步就从React.Component的实现开始。 类实现的组件有自己私有的state,同时可以通过this.props来获取传进来的参数。
React.component
React.Component
state
this.props
function Component(props) { this.props = props this.state = {} }
我们知道在react中,我们可以通过setState来改变组件state的值,而且当state改变后,组件对应的也会重新渲染。
setState
Object.assign
render
Component.prototype.setState = function (updateState) { // 更新 state this.state = Object.assign({}, this.state, updateState) // 重新渲染组件 render(this) }
在上一节中,我们知道ReactDom.render(),会将其第一个参数转成React.createElement()形式,而组件也会被转为React.createElement(Hello, null)这种形式。
ReactDom.render()
React.createElement()
React.createElement(Hello, null)
所以react中组件在渲染时会被当成函数渲染的。所以我们在render函数中需要判断虚拟dom的标签属性(此处用tag表示的)是函数还是原生dom。如果是函数的话,我们只需要拿到组件的jsx转换后对应的虚拟dom, 然后在进行渲染。
tag
jsx
const render = (vdom, root) => { if (typeof vdom.tag === 'function') { let component if (vdom.tag.prototype.render) { // 类定义的组件, vdom.attrs 是传入的 props component = new vdom.tag(vdom.attrs) } else { // 函数定义组件 component = vdom.tag(vdom.attrs) } return _render(component, root) } _render(vdom, root) }
对应的_render():
const _render = (vdom, root) => { // 类组件的话,需要从 render 函数中拿到 jsx 转换后的虚拟 dom const vdomNode = vdom.render ? vdom.render() : vdom if (typeof vdomNode === "string" || typeof vdomNode === "number") { root.innerText += vdomNode return } const dom = document.createElement(vdomNode.tag) if (vdomNode.attrs) { for (let attr in vdomNode.attrs) { const value = vdomNode.attrs[attr] setAttribute(dom, attr, value) } } // 遍历子节点, 渲染子节点 vdomNode.childs && vdomNode.childs.forEach(child => render(child, dom)) // 将父节点 root 挂到 vdom 上,当再次渲染组件时,跟据 vdom.root 直接渲染 dom if (vdom.root) { vdom.root.innerText = '' vdom.root.appendChild(dom) return } vdom.root = root // 将子元素挂载到其真实 DOM 的父元素上 root.appendChild(dom) }
试一试,刚出锅的代码效果如何。
import React from "./react" import ReactDom from "./reactDom" const World = props => { return ( <h1> world!<p>{props.world}</p> </h1> ) } class Hello extends React.Component { constructor(props) { super(props) this.state = { count: 0 } } addCount() { const { count } = this.state this.setState({ count: count + 1 }) } render() { return ( <div ha="lou"> hello <World world="function props" /> <span>{this.props.initProps}</span> <div>{this.state.count}</div> <button onClick={this.addCount.bind(this)}> + </button> </div> ) } } ReactDom.render( <Hello initProps="this is props" />, document.getElementById("root") )
react在渲染组件时,组件会被babel转为React.createElement(fn, null)这种形式,第一参数是函数,所以我们需要从fn中获取由组件的jsx转换后的虚拟dom,然后在将虚拟dom渲染成真实dom。 setState:在调用setState时,先用Object.assign更新state的值,然后重新渲染组件。 附上本文代码
babel
React.createElement(fn, null)
fn
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
本文主要参考了从零开始实现一个React和从 0 到 1 实现React
在上一节JSX和虚拟DOM中,我们了解了
react
中的JSX
到虚拟dom
,以及如何将虚拟dom
渲染成真实的dom
。在这一节中,我们将会了解react
中组件是如何渲染的。组件
在
react
中,组件有两种使用方法:通过类定义组件时,是需要继承
React.component
的,我们第一步就从React.Component
的实现开始。类实现的组件有自己私有的
state
,同时可以通过this.props
来获取传进来的参数。setState
我们知道在
react
中,我们可以通过setState
来改变组件state
的值,而且当state
改变后,组件对应的也会重新渲染。state
的值:我们可以使用Object.assign
来实现。state
值后,调用render
函数,重新渲染。异步的setState
在后面的章节会实现。渲染
在上一节中,我们知道
ReactDom.render()
,会将其第一个参数转成React.createElement()
形式,而组件也会被转为React.createElement(Hello, null)
这种形式。所以
react
中组件在渲染时会被当成函数渲染的。所以我们在render
函数中需要判断虚拟dom
的标签属性(此处用tag
表示的)是函数还是原生dom
。如果是函数的话,我们只需要拿到组件的jsx
转换后对应的虚拟dom
, 然后在进行渲染。对应的_render():
试一试,刚出锅的代码效果如何。
小结
react
在渲染组件时,组件会被babel
转为React.createElement(fn, null)
这种形式,第一参数是函数,所以我们需要从fn
中获取由组件的jsx
转换后的虚拟dom
,然后在将虚拟dom
渲染成真实dom
。setState
:在调用setState
时,先用Object.assign
更新state
的值,然后重新渲染组件。附上本文代码
The text was updated successfully, but these errors were encountered: