React Component vs React Element

有这样的一个问题:

// 方法定义
function add(x, y) {return x + y
}// 方法调用
add(1, 2)// 组件定义
class Icon extends Component {}// 组件调用??????
<Icon />

最后的一句<Icon />用专业的词概括是什么操作,组件调用还是什么?

有答“组件声明”的,有答“组件调用的”,有“组件初始化”的,还有“使用一个组件”的。没有一个统一的称呼。造成这样局面的原因是很多时候我们都没有去详细的了解过JSX和React实际操作之间的抽象层。现在我们就深入研究一下这部分知识。

我们来看看最基础的问题,什么是React?React就是一个用来写界面的库。不管React和React的生态有多复杂,最核心的功能就是用来写界面的。那么我们来看看Element,很简单,但是一个React element描述的就是你想要在界面上看到的。再深入一点,一个React element就是一个代表了DOM节点的对象。注意,一个React element并不是在界面上实际绘制的东西,而是这些内容的代表。由于JavaScript对象是轻量级的,React可以任意的创建和销毁这些element对象,而且不用担心太大的消耗。另外,React可以分析这些对象,把当前的对象和之前的对象对比,找出发生的改变,然后根据实际发生的改变来更新实际的DOM。

为了创建一个DOM节点的代表对象(也就是React element),我们可以使用React的createElement方法。

const element = React.createElement('div',{id: 'login-btn'},'Login'
)

createElement方法传入了三个参数。第一个是标签名称字符串(div、span等),第二个是给element设置的属性,第三个是内容或者是子的React element。本例中的“Login”就是element的内容。上面的createElement方法调用后会返回一个这样的对象:

{type: 'div’,props: {children: 'Login',id: 'login-btn'}
}

当这个对象绘制为DOM(使用ReactDOM.render方法)的时候,我们就会有一个新的DOM节点:

<div id='login-btn'>Login</div>

有一个很有意思的地方,我们在学React的时候首先注意到的就是component(组件)。“Components(组件)是React的构建块”。注意,我们是以element开始本文的。而且你一旦理解了element,理解component也就是水到渠成的事了。一个component就是一个方法或者一个类,可以接受一定的输入,之后返回一个React element。

function Button({onLogin}) {return React.createElement('div',{id: 'login-btn', onClick: onLogin},'Login')
}

在上面的定义中,我们有一个Button组件(component)。接收一个onLogin输入并返回一个React element。注意,Button组件接收的onLogin方法是它的prop。然后把这个方法通过createElement方法的第二个参数传入到了实际的DOM里。

更深入一点

目前,我们只接触到了使用HTML元素来创建React element,比如“div”、“span”等。其实,你也可以把其他的React component(组件)作为第一个参数传入createElement方法。

const element = React.createElement(User,{name: 'Uncle Charlie'},null
)

然而,不同于一般的HTML标签名称,React如果发现第一个参数是class或者function类型的话,它就会检查传入的参数要绘制的是一个什么element,传入必要的props。之后React会一直检查,直到没有方法或者类作为第一个参数传入createElement。我们来看看下面的例子:

function Button({addFriend}) {return React.createElement('button',{onClick: addFriend},'Add Friend')
}function User({name, addFriend}) {return React.createElement('div',null,React.createElement('p',null,name),React.createElement(Button, {addFriend}))
}

上面的例子里有两个component(组件)。一个Button,一个User。User“代表”了一个div,div里面有两个子节点:一个包含用户名的“p”和一个Button组件。现在我们看看上面的例子的具体的调用过程。

function Button({addFriend}) {return {type: 'button',props: {onClick: addFriend,children: 'Add Friend'}}
}function User({name, addFreind}) {return {type: 'div',props: {children: [{type: 'p',props: {children: name}},{type: Button,props: {addFriend}}]}}
}

在上面的代码里你会看到四种不同的属性:“button”,“div”,“p”和Button。当React看到一个element是function和类类型的话,它就会检查element会返回什么element,并传入对应的props。在这个过程结束之后,React就拥有了一个代表DOM树的对象的数。上面的例子最后的结构是这样的:

{type: 'div',props: {children: [{type: 'p',props: {children: 'Tyler McGinnis'}},{type: 'button',props: {onClick: addFriend,children: 'Add Friend'}}]}
}

上面叙述的整个过程叫做Reconciliation(这个不知道怎么翻译,应该叫和谐?)。在React里,每次调用setState方法或ReactDOM.render方法被调用的时候都会触发这个过程。

那么我们来看看最开始的问题:

// 方法定义
function add(x, y) {return x + y
}// 方法调用
add(1, 2)// 组件定义
class Icon extends Component {}// 组件调用??????
<Icon />

现在我们已经有了回答这个问题的全部知识,除了一点点以外。有个地方,你可能觉得奇怪在使用React的时候,从来没有用过createElement方法来创建element。你是用了JSX。我(作者)最开始的时候说:“主要原因是从来没有去详细的了解过JSX和React实际操作之间的抽象层”。这个抽象层就是JSX会被Babel转码为React.createElement方法的调用。

看看我们前面的例子:

function Button({addFriend}) {return React.createElement('button',{onClick: addFriend},'Add Friend')
}function User({ name, addFriend }) {return React.createElement("div",null,React.createElement("p",null,name),React.createElement(Button, { addFriend }))
}

写成JSX的样子是这样的:


function Button({addFriend}) {return (<button onClick={addFriend}>Add Friend</button>)
}function User({name, addFriend}) {return (<div><p>{name}</p><Button addFriend={addFriend} /></div>)
}

所以,最后我们应该怎么回答前面的问题呢?<Icon />叫做什么?

应该叫做“创建element”,应为JSX最后会转码为createElement方法的调用:

React.createElement(Icon, null)

前面的例子都是“创建一个React element”。

React.createElement('div',{ className: 'container' },'Hello!'
)<div className='container'>Hello!</div><Hello />

原文地址:https://tylermcginnis.com/rea...

React Component vs React Element相关推荐

  1. React.Component与React.PureComponent的区别

    转发自:https://blog.csdn.net/qq_29854831/article/details/79657718 React.PureComponent 与 React.Component ...

  2. [译]React Component最佳实践

    原文:Our Best Practices for Writing React Components . 这里意译.有些点在之前的文章里提到过:#2 译文地址:https://github.com/Y ...

  3. 六、React(Component)

    文章目录 前言 一.component基础 二.Component的组合运用 总结 前言 本文介绍react的重中之重,react的组件.组件是react的核心所在,第一部分先介绍组件的基础内容,并且 ...

  4. 【重点】React.Component用法

    组件(Components)允许您将UI拆分为独立的可重用的部分,并单独的考虑每个部分. 总览 React.Component是一个抽象基类.这意味着直接引用React.Component是毫无意义的 ...

  5. React的React.FC与React.Component的初步认识

    React 的组件可以定义为 函数(React.FC<>)或class(继承 React.Component) 的形式. 一.React.FC<> 1.React.FC是函数式 ...

  6. React的React.FC与React.Component

    React的组件可定义为函数(React.FC<>)或class(继承React.Componnent)的形式 ###React.FC<> 1.React.FC是函数式组件 是 ...

  7. React笔记:React基础(2)

    1. JSX JSX是一种拥有描述UI的JavaScript扩展语法,React使用这种语法描述组件的UI. 1.1 基本语法 JSX可以嵌套多个HTML标签,可以使用大部分符号HTML规范的属性. ...

  8. React解密:React高阶组件是什么?

    React中比较高大上的东西,高阶组件应该算是一个点,开发中也许写的不多,但是我们必须要直到高阶组件是什么,高阶组件能干什么? A higher-order component is a functi ...

  9. 从零开始React:一档 React环境搭建,语法规则,基础使用

    手挽手带你学React入门第一期,带你熟悉React的语法规则,消除对JSX的恐惧感,由于现在开发中都是使用ES6语法开发React,所以这次也使用ES6的模式进行教学,如果大家对ES6不熟悉的话,先 ...

最新文章

  1. DCN-2655 同异步端口PPP (chap)认证
  2. 怎么去除桌面图标显示快捷方式字样?
  3. 模板实参推导 xx_cast的实现
  4. 【LDA学习系列】LDA-Python库
  5. apache的斜杠问题
  6. Centos 磁盘管理及配额管理
  7. apache访问快捷方式
  8. C# 解决窗体假死的状态
  9. 胜利大逃亡 三维BFS
  10. CS61c Fall 2019 project1
  11. linux网络Netfilter与iptables技术
  12. 条件运算符 c语言,C语言 —— 条件运算符
  13. 从谷歌搜索结果页中提取url与域名
  14. App开屏页如何设计?来看这五个常用的方法
  15. html+css精致的登录页面 (含源码的哦)
  16. 什么是EDM营销?EDM营销和一般营销方式的区别分析
  17. 微信公众号开启服务器配置流程及注意事项
  18. 推荐系统——(论文阅读笔记)YouTube的视频推荐系统
  19. [BZOJ 4763]雪辉
  20. JAVA组合框怎么添加加减乘除,[C#]组合框设计windows加减乘除简单计算器应用

热门文章

  1. 在Centos中安装aria2c
  2. android 51 有序广播
  3. C#.NET通用权限管理在DB2数据库上运行的脚本参考 - 序列创建脚本参考
  4. java 编写小工具 尝试 学习(四)
  5. 程序员经常去的 14 个顶级开发者社区(转)
  6. 【转】【C#】C#重绘windows窗体标题栏和边框
  7. 关于Google Map API V2 版本的定位与导航
  8. Linux系统端口聚合技术bonding
  9. 看BAT技术面试官如何挑选Java程序员
  10. [译]Kotlin + buildSrc:更好的管理Gadle依赖