React Component vs React Element

2023-05-16

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...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React Component vs React Element 的相关文章

  • 如何在VB中从数组元素中得出所有可能的总和组合

    如果有一个数组 其中元素为 1 2 3 4 则程序应返回另一个数组 其中包含所有组合的总和 1 2 3 4 3 1 2 4 1 3 5 1 4 5 2 3 6 2 4 7 3 4 6 1 2 3 7 1 2 4 8 1 3 4 9 2 3
  • Polymer-AngularJS 双向数据绑定

    我创建了一些自定义元素Polymer 我们称之为 x input 它看起来像这样
  • 数组中最常见的值

    我将如何找到数组中三个最常见的元素 我正在处理长度为 10 000 的数组 其元素 0 100 之间的随机整数 我正在考虑使用两个数组 其中一个长度为 100 并且通过使用 if 语句来递增 但是 我想知道是否有一种方法可以仅使用一个 fo
  • 如何从 NSDictionary 中选择随机键?

    当我使用 NSArray 时 这很简单 NSArray array lastIndex INT MAX int randomIndex do randomIndex RANDOM INT 0 array count 1 while rand
  • 仅将混合模式应用于投影

    可以混合吗only元素的投影与它重叠的元素的颜色 例如 我有一个元素与另一个元素重叠 顶部的元素有一个浅灰色的阴影 下面的元素是黑色的 我不希望对任何一个元素本身应用任何混合 但希望重叠元素 的投影与下面元素的颜色混合 在阴影落在重叠元素上
  • Joomla 2.5 Jquery 无法调用 null 的方法

    大家好 我正在使用 Joomla 2 5 和 Jquery 我在 chrome 控制台中遇到了这个奇怪的错误 Uncaught TypeError Cannot call method slideUp of null 这是index php
  • MongoDB C# - 获取不存在的元素的 BsonDocument

    所以我有一个 BsonDocument b 假设它有 FirstName LastName Age 您可以通过 b FirstName 等访问它 如果我尝试执行 b asdfasdf 当然不存在 它不会返回 null 而是会导致应用程序出错
  • HTML 元素过多会影响页面性能吗?

    我想知道两者之间是否有区别 1 10 000 个可见的表行 2 使用 display none 隐藏 10 000 个表格行 我想知道的是 如果页面上所有 10 000 行都可见 是否会导致页面滚动滞后 但如果我隐藏其中的 9000 个 这
  • jQuery 注释/取消注释

    我正在寻找一种使用 jQuery 将元素包装到注释中的方法 例如 还有一种删除评论的方法 这可能吗 要使用注释包装元素 或者更具体地说 用具有该元素 HTML 的注释节点替换元素 my element jq my element comme
  • 检查 div ID 是否存在 (PHP)

    PHP 可以检查元素是否存在吗 我已经知道 javascript 方法 但我只是想尽可能避免它 如果你有 HTML 服务器端的字符串 你可以使用DOM文档 http php net manual en class domdocument p
  • 获取显示器内部元素的大小:无父级

    我正在尝试获取将在 jquery ui 对话框中显示的元素的宽度 该对话框设置为在加载时显示 无 这不允许我获得宽度 我是否需要显示它 获取宽度并立即再次隐藏它以获取宽度 或者还有其他我不知道的选择吗 Thanks 您有两个选择 如果你的
  • Vuejs 元素值变化事件?

    我有一个元素想要观察这样的变化 span class lower 50 span 用 vuejs 可以干净地做到这一点吗 我尝试查看文档 但找不到类似的内容 我想在 VueJs 中每当 50 更改为其他内容时启动一个自定义事件 你有没有尝试
  • R:删除向量的最后一个元素

    如何删除动物园系列的最后 100 个元素 我知道名称 元素 符号 但我无法减去整个部分 我喜欢用head因为这样更容易打字 其他方法可能执行得更快 但我很懒 而我的计算机却不是 x lt head x 100 gt head 1 102 1
  • 如何在Python中删除两个numpy数组的重复元素

    我有两个数组命名 u v 例如 u np array 1 0 2 0 2 0 3 0 4 0 v np array 10 0 21 0 18 0 30 0 40 0 a np array 100 0 210 0 220 0 300 0 40
  • 在Java中一次向ArrayList添加多个项目[重复]

    这个问题在这里已经有答案了 如何一次向 ArrayList 添加多个项目 ArrayList
  • Lua:“拖动”数组中的元素序列

    我正在尝试创建一个函数 将连续数量的元素 拖动 到数组中的新位置 并限制为数组的当前大小 其他项目应该围绕 拖动 的项目晃动 例如 如果我的数组有 7 个元素 并且我想拖动中间的三个 1 2 3 4 5 6 7 lt keys a b C
  • Jquery Draggables:删除元素会更改其他删除元素的位置

    当放置 放置元素 通过从一个 DIV 拖动到另一个 DIV 然后删除放置的 DIV 中的一个元素时 其中一些元素会更改位置 这是一个测试场景 http jsfiddle net TcYHW 8 http jsfiddle net TcYHW
  • 两个列表中的公共元素

    我有两个ArrayList每个对象都有三个整数 我想找到一种方法来返回两个列表的共同元素 有人知道我该如何实现这一目标吗 Use Collection retainAll https docs oracle com en java java
  • CSS,悬停一个元素,影响另一个元素

    当我将鼠标悬停在 li a 上时 我可以影响普通 CSS 中的另一个元素吗 因为我试图在悬停链接时将一个框作为背景元素滑入 与此网站导航完全相同 只是不是在激活时使用 而是通过悬停来使用 http www zindhai com http
  • 计算数组元素的出现次数/频率

    在 Javascript 中 我试图获取一个初始的数值数组并计算其中的元素 理想情况下 结果将是两个新数组 第一个指定每个唯一元素 第二个包含每个元素出现的次数 不过 我愿意接受有关输出格式的建议 例如 如果初始数组是 5 5 5 2 2

随机推荐

  • sql 语句中如何写判断

    当ID为26时 xff0c 查询的result是ok span class token keyword select span name span class token punctuation span span class token
  • 光流定位原理是什么??【转】

    转自 xff1a https www zhihu com question 35980316 Jessie Lee HIT 控制 无人机 光流是测速算法 xff0c 并不是直接定位的 简单理解 xff0c 光流就是通过检测图像中光点和暗点的
  • 算法杂货铺——分类算法之决策树(Decision tree)

    3 1 摘要 在前面两篇文章中 xff0c 分别介绍和讨论了朴素贝叶斯分类与贝叶斯网络两种分类算法 这两种算法都以贝叶斯定理为基础 xff0c 可以对分类及决策问题进行概率推断 在这一篇文章中 xff0c 将讨论另一种被广泛使用的分类算法
  • 01-嵌入式入门-如何看原理图

    最近由于找到的工作是偏于嵌入式方向 xff0c 因此又重新开始学习已经丢弃两年的知识 新手学习知识感觉有一个通病 xff1a 喜欢收集各种各样的视频 资料 xff0c 网盘里收藏一大堆 xff0c 但是却从没有打开看过 xff0c 到头来还
  • MAVLink v1.0详解——结构

    本文针对 MAVLink v1 0版本 xff0c 协议版本 xff1a 3 MAVLink是为微型飞行器MAV xff08 Micro Air Vehicle xff09 设计的 xff08 LGPL xff09 开源的通讯协议 是无人飞
  • ECMAScript6——数组操作方法_总结篇

    ES6 gt 数组的方法 加粗为ES6新增的方法 1 pop 删除数组的最后一个元素 xff0c 把数组的长度减1 xff0c 并且返回它被删除元素的值 xff0c 如果数组变为空 xff0c 则该方法不改变数组 xff0c 返回undef
  • 网络工程师十个常见面试问题

    1 1 简单说一下OSI七层 Osi模型是一个工业的标准 它为现在的互联网提供了很大的贡献 是一个逻辑上的规范和标准 xff0c 很多厂商都要遵循它 他定义了七层每一层都有不同的功能和规范 物理层 物理层定义了设备接口上的一些电子电气化的标
  • 像素、分辨率、DPI

    Q xff1a 我们平时买数码相机时 xff0c 说的200万像素 xff0c 300万像素 xff0c 这个像素是什么意思 xff1f A xff1a 像素 xff08 Pixel xff09 是由Picture和Element这两个单词
  • Apache 目录索引样式 mod_autoindex

    apache 的目录索引样式用的mod autoindex模块 一般默认为开启状态 我们直接配置httpd conf文件 讲如下内容加到HTTD CONF Options Indexes FollowSymLinks IndexOption
  • ubuntu网卡名称变化的解决方法

    在chinacache工作时 xff0c 遇到了东方网力的客户 xff0c 需要安装使用ubuntu系统 xff0c 每个服务器有4个网口 xff0c 在做bond时 xff0c 发现部分网卡漂移 xff0c 为了解决这个 xff0c 搜索
  • C# 给DataGridView加多选框

    span class token comment 多选框 span DataGridViewCheckBoxColumn dgCheck span class token operator 61 span new DataGridViewC
  • Java架构进阶之路——阿里大牛强力推荐书单(附赠电子版)

    1 深入理解Java虚拟机 xff1a JVM高级特性与最佳实践 本书适合所有Java程序员 系统调优师和系统架构师阅读 共分为五大部分 xff0c 围绕内存管理 执行子系统 程序编译与优化 高效并发等核心主题对JVM进行了全面而深入的分析
  • ModemManager

    ModemManager是D Bus激活的守护进程 xff0c 用来控制移动宽带 xff08 2G 3G 4G xff09 设备和连接 xff0c 提供统一的高层API接口 说白了就是可以用来管理上网卡 ModemManager可以管理内置
  • odroidxu4linux,2019年值得期待的5个树莓派替代品

    说到卡片电脑 xff0c 树莓派是当之无愧的热门 这款售价35美元的微型计算机已经在全球范围内吸引了众多爱好者 xff0c 因为它能够以商业设备的一小部分价格执行基于PC的功能 当然 xff0c 它或许不是最强大或最便宜的微型计算机 xff
  • ros 发布信息频率_工具使用-ROS中使用publisher、subscriber发布订阅topic

    Publisher Node 不同于cpp文件一般存在package下的src文件夹 xff0c python文件一般存储在package下的scripts文件夹下 1 2 3 4roscd beginner tutorials scrip
  • 轨迹系列1——一种基于路网图层的GPS轨迹优化方案

    文章版权由作者李晓晖和博客园共有 xff0c 若转载请于明显处标明出处 xff1a http www cnblogs com naaoveGIS 1 背景 GPS数据正常情况下有20M左右的偏移 xff0c 在遇到高楼和桥梁等情况下偏移会更
  • 材料研究方法

    编程是非常有意思的 xff0c 可是作为材料人 xff0c 学好材料才是比较重要的事情 xff0c 下面记录一些知识点 光学透镜的成像原理 光的折射 光在均匀介质中沿直线传播 在不同介质中光的传播速度不同 当光从一种介质传播到另一种介质中去
  • [微信小程序系列] 动画案例之圆点沿着圆圈运动

    作者 xff1a 滴滴公共前端团队 Tawnia 滴滴作为第一批的小程序开发者 xff0c 我们也大量地用到了动画 xff0c 积累了一些经验 xff0c 由于市面上的小程序动画案例很少 xff0c 我们也分享一部分我们做过的案例 xff1
  • Vue Iview Tree插件的无限层

    Iview lt template gt lt Tree data 61 34 baseData 34 show checkbox multiple gt lt Tree gt lt template gt lt script gt exp
  • React Component vs React Element

    React Component vs React Element 有这样的一个问题 xff1a 方法定义 function add x y return x 43 y 方法调用 add 1 2 组件定义 class Icon extends