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 的相关文章

  • 黑马React:基础拓展

    黑马React D10 基础拓展 Date December 18 2023 useReducer 基础使用 作用 让 React 管理多个 相对关联 的状态数据 补充 和useState的作用类似 用来管理相对复杂的状态数据 特点 use
  • Jquery无法在回调函数中访问$(this)

    我正在创建一个插件 但它无法访问 this 我的插件的简单概述是 function fn myPlugin function options callback return this each function this click fun
  • 如何计算 Ruby 数组中相同字符串元素的数量

    我有以下内容Array Jason Jason Teresa Judah Michelle Judah Judah Allison 我如何为每个生成一个计数相同的元素 Where Jason 2 Judah 3 Allison 1 Tere
  • React安装依赖 node_modules中有下载依赖项但package.json文件中没有依赖

    React安装依赖 node modules中有下载依赖项但package json文件中没有依赖 直接在下载依赖项后 加 S 就可以解决 随机 id 生成器 uuid nanoid npm install nanoid S S save
  • TYPO3:如何在后端添加css和JS

    我该如何添加css and javascript后端有文件吗 我想将这些文件用于自定义创建的内容元素以使它们对用户更具吸引力 System TYPO3 v9 Mode 作曲家模式 Target 自定义内容元素 在 TYPO3 v9 中 您必
  • jQuery 选择具有相同类的随机元素

    我有 selectElement 类的元素 当我单击具有该类的元素时 我 选择 它 并给它另一个类 selectedElements 如果它还没有 但是 我有一个按钮 应该随机选择一定数量 例如 10 的 selectElement 类元素
  • Vuejs 元素值变化事件?

    我有一个元素想要观察这样的变化 span class lower 50 span 用 vuejs 可以干净地做到这一点吗 我尝试查看文档 但找不到类似的内容 我想在 VueJs 中每当 50 更改为其他内容时启动一个自定义事件 你有没有尝试
  • 从 C# 中的 List 中选择 N 个随机元素

    我需要一个快速算法从通用列表中选择 5 个随机元素 例如 我想从 a 中获取 5 个随机元素List
  • R:删除向量的最后一个元素

    如何删除动物园系列的最后 100 个元素 我知道名称 元素 符号 但我无法减去整个部分 我喜欢用head因为这样更容易打字 其他方法可能执行得更快 但我很懒 而我的计算机却不是 x lt head x 100 gt head 1 102 1
  • JQuery 选择框和循环帮助

    谢谢阅读 我对 jQuery 有点陌生 我正在尝试制作一个可以包含在我所有网站中的脚本来解决一个总是让我发疯的问题 问题 带有长选项的选择框在 Internet Explorer 中会被截断 例如 这些选择框 http discoverfi
  • Jquery Draggables:删除元素会更改其他删除元素的位置

    当放置 放置元素 通过从一个 DIV 拖动到另一个 DIV 然后删除放置的 DIV 中的一个元素时 其中一些元素会更改位置 这是一个测试场景 http jsfiddle net TcYHW 8 http jsfiddle net TcYHW
  • jquery遍历新创建的元素

    我正在尝试在表中添加新行 并将它们保存到数据库中 首先 我使用 append 在表中追加行 tablename append tr td newly added row td tr 附加功能运行良好 我的页面显示了正确的结果 但是 我无法选
  • 如何在批处理中返回数组的元素?

    我的程序中的数组列表中有两个元素 如何将变量分配给等于其中一个元素 这是代码 echo off setlocal enabledelayedexpansion set p string for l a in 0 1 1000 do if n
  • 访问或解析 R 中的 summary() 中的元素

    我运行以下 R 命令来进行 Dunnett 测试并获取摘要 如何访问下面线性假设的每一行 这是摘要输出的一部分 基本上我不知道摘要的结构 我尝试使用名称 但它似乎不起作用 因为我没有看到任何命名属性来提供这一点 library multco
  • 是否可以获取绑定到 jQuery 元素的事件列表?

    正如问题所说 我需要绑定到特定元素的事件列表 我的意思是像单击 鼠标悬停等事件在 dom 加载时绑定到该元素 愚蠢 示例 element click function stuff element mouseover function stu
  • 枚举类型的 JAXB 元素

    所以我知道如何创建枚举类型 但是当我为其设置元素类型时 元素字段将只是字符串类型 而不是枚举类型 如何在我的模式中创建枚举并让 JAXB 将其生成为 java 枚举类型 这就是我创建枚举类型和元素的方式
  • AngularJS 指令 - 设置多个指令元素的顺序(不是指令的优先级,而是元素的优先级)

    考虑带有指令 foo 的标记 div div div div div div 使 foo 按指定顺序而不是从上到下 3 1 2 运行的好方法是什么 我唯一能想到做的就是跟踪已运行的内容并在不按顺序的项目上返回 false 然后让 Angul
  • C++ 编译器可以对结构中的元素重新排序吗

    C 编译器 特别是 g 可以对结构体的内部元素重新排序吗 我看到一些奇怪的行为 其中我有一个包含如下内容的结构 Struct SomeStruct long someLong long someLongArray 25 unsigned l
  • Jquery,在悬停时添加和删除元素

    我遇到了一个问题 我尝试了几乎所有方法都没有解决 a hovered hover function this after img src images icons famfamfam silk user go png function th
  • 如何解决 TypeError: element_to_be_clickable() 需要 1 个位置参数?

    我收到错误TypeError element to be clickable takes 1 positional argument but 2 were given当我运行以下代码时 from selenium webdriver chr

随机推荐

  • 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