内容简介:在上一节在通过类定义组件时,是需要继承
在上一节 JSX和虚拟DOM 中,我们了解了 react
中的 JSX
到虚拟 dom
,以及如何将虚拟 dom
渲染成真实的 dom
。在这一节中,我们将会了解 react
中组件是如何渲染的。
组件
在 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
来获取传进来的参数。
function Component(props) { this.props = props this.state = {} } 复制代码
-
setState
我们知道在 react
中,我们可以通过 setState
来改变组件 state
的值,而且当 state
改变后,组件对应的也会重新渲染。
- 改变
state
的值:我们可以使用Object.assign
来实现。 - 重新渲染组件:我们可以在改变
state
值后,调用render
函数,重新渲染。异步的setState
在后面的章节会实现。
Component.prototype.setState = function (updateState) { // 更新 state this.state = Object.assign({}, this.state, updateState) // 重新渲染组件 render(this) } 复制代码
渲染
在上一节中,我们知道 ReactDom.render()
,会将其第一个参数转成 React.createElement()
形式,而组件也会被转为 React.createElement(Hello, null)
这种形式。
react
中组件在渲染时会被当成函数渲染的。所以我们在
render
函数中需要判断虚拟
dom
的标签属性(此处用
tag
表示的)是函数还是原生
dom
。如果是函数的话,我们只需要拿到组件的
jsx
转换后对应的虚拟
dom
, 然后在进行渲染。
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") ) 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 细说 Vue 组件的服务器端渲染
- (译)Vue.js 构建一个"无渲染"组件
- React 组件模式-有状态组件 x 无状态组件、容器组件 x 展示组件、高阶组件 x 渲染回调(函数作为子组件)
- React源码分析与实现(一):组件的初始化与渲染
- 支持大数据渲染下拉列表组件开发 SuperSelect(基于antd Select)
- reactjs – 使用react-router-dom进行组件渲染时更改Url?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Think Python
Allen B. Downey / O'Reilly Media / 2012-8-23 / GBP 29.99
Think Python is an introduction to Python programming for students with no programming experience. It starts with the most basic concepts of programming, and is carefully designed to define all terms ......一起来看看 《Think Python》 这本书的介绍吧!