React基础-工作原理

在React的世界里,我们使用React Elements、ReactDOM和React Components这三个核心概念来构建我们的应用。在本篇文章中,我们将详细解析这三个概念,并通过实例代码来展示它们的使用方法。

HTML页面准备

首先,我们打开已经创建好的项目,在index.html文件中可以看到<div id="root"></div>标签,之后我们的代码将会挂载到该id为root的DOM标签上。

React Elements 与 ReactDOM

React Element :React Element是React应用的最小构建块。它描述了在屏幕上看到的内容。在代码中,React Element通常由React.createElement()方法创建。

ReactDOM:ReactDOM提供了一种将React Element渲染到DOM的方法。

React.createElement()方法接收三个参数:

  • 参数1:元素类型(如"h1")
  • 参数2:元素属性(如null)
  • 参数3:元素的子元素(如"辰火流光的React学习笔记")
tsx 复制代码
// main.tsx文件
import React from "react";
import ReactDOM from 'react-dom/client'

// 创建了一个表示`<h1>`标签的React Element
const tagH1 = React.createElement("h1", null, "辰火流光的React学习笔记");

// 将上面创建的`tagH1`元素渲染到id为"root"的DOM元素中
ReactDOM.createRoot(document.getElementById('root')!).render(tagH1)

在这个例子中,ReactDOM.createRoot()方法创建了一个根React元素,然后render()方法将tagH1元素渲染到<div id="root"></div>元素中。

在浏览器中效果

在TypeScript类型声明文件中,我们可以看到createRoot函数返回的是一个Root类型的对象。这个Root接口中包含了两个方法,其中render方法接收的参数类型为React.ReactNode

React.ReactNode是React中定义的一种类型,它包括了我们可以在React组件中渲染的所有类型的值,包括字符串、数字、React元素、数组、Fragment等。这意味着我们可以将这些类型的值作为参数传递给render方法。

例如,我们可以创建两个React元素,然后将它们放在一个数组中,作为参数传递给render方法:

tsx 复制代码
import React from "react";
import ReactDOM from 'react-dom/client'

const tagH1 = React.createElement("h1", null, "辰火流光");
const tagH2= React.createElement("h2", null, "React学习笔记");
ReactDOM.createRoot(document.getElementById('root')!).render([tagH1,tagH2])

在浏览器中的效果

然而,当我们这样做时,浏览器的控制台会出现一个警告:Each child in a list should have a unique "key" prop.。这是因为当我们在React中渲染数组时,每个元素都需要一个唯一的key属性。

key属性是React用来追踪哪些元素被修改、添加或删除的一种方式。在这个例子中,我们可以通过添加key属性来解决这个警告:

tsx 复制代码
import React from "react";
import ReactDOM from 'react-dom/client'

const tagH1 = React.createElement("h1", {key: "h1"}, "辰火流光");
const tagH2= React.createElement("h2", {key: "h2"}, "React学习笔记");
ReactDOM.createRoot(document.getElementById('root')!).render([tagH1,tagH2])

现在假设我们要创建以下html:

html 复制代码
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
</ul>

我们可以使用React.createElement函数来逐一创建每个li元素,然后将它们作为子元素传递给ul元素:

tsx 复制代码
import React from "react";
import ReactDOM from 'react-dom/client'

const tagUL=React.createElement(
    "ul",
    null,
    React.createElement("li", {key:1}, "Item 1"),
    React.createElement("li", {key:2}, "Item 2"),
    React.createElement("li", {key:3}, "Item 3"),
    React.createElement("li", {key:4}, "Item 4"),
    React.createElement("li", {key:5}, "Item 5"),
    React.createElement("li", {key:6}, "Item 6")

);

ReactDOM.createRoot(document.getElementById('root')!).render(tagUL)

然而,这种方式存在一定的局限性。如果列表项的数量或内容需要根据数据动态变化,那么手动创建每个元素就会变得非常繁琐。这时,我们可以利用JavaScript的数组映射方法(map)来动态生成元素。

我们可以先定义一个包含所有列表项内容的数组,然后使用map方法将每个内容映射为一个li元素:

tsx 复制代码
import React from "react";
import ReactDOM from 'react-dom/client'

const items = [
    "Item 1",
    "Item 2",
    "Item 3",
    "Item 4",
    "Item 5",
    "Item 6",
];
const tagUL=React.createElement(
    "ul",
    null,
    items.map((item,index) => React.createElement("li", {key:index}, item))
);

ReactDOM.createRoot(document.getElementById('root')!).render(tagUL)

在浏览器中的效果

这样,无论列表项的数量或内容如何变化,我们都可以轻松地生成对应的列表。

需要注意的是,当我们在React中渲染数组时,每个元素都需要一个唯一的key属性。这是因为key属性可以帮助React识别哪些元素被修改、添加或删除,从而提高渲染性能。

React Components

React Component是一种函数或类,它接收输入(称为"props")并返回一个React Element。例如,以下代码定义了一个名为"MyComponent"的函数组件:

tsx 复制代码
import React from "react";
import ReactDOM from 'react-dom/client'

function MyComponent() {
    return React.createElement(
        "ul",
        { className: "myClass" },
        React.createElement("li", null, "Item 1"),
        React.createElement("li", null, "Item 2"),
        React.createElement("li", null, "Item 3"),
        React.createElement("li", null, "Item 4"),
        React.createElement("li", null, "Item 5"),
        React.createElement("li", null, "Item 6"),
    );
}

ReactDOM.createRoot(document.getElementById('root')!).render(React.createElement(MyComponent, null, null))

tsx 复制代码
import React from "react";
import ReactDOM from 'react-dom/client'

const items = [
    "Item 1",
    "Item 2",
    "Item 3",
    "Item 4",
    "Item 5",
    "Item 6",
];

function MyComponent() {
    return React.createElement(
        "ul",
        { className: "myClass" },
        items.map((item,index) => React.createElement("li", {key:index}, item))
    );
}

ReactDOM.createRoot(document.getElementById('root')!).render(React.createElement(MyComponent, null, null))

在这个例子中,MyComponent函数返回了一个表示<ul>标签的React Element,这个<ul>标签包含了六个<li>标签的子元素。

在浏览器中的效果

组件传参:

React Component可以接收props作为输入。例如,以下代码将一个包含六个item的数组作为props传递给MyComponent组件:

tsx 复制代码
import React from "react";
import ReactDOM from 'react-dom/client'

const items = [
    "Item 1",
    "Item 2",
    "Item 3",
    "Item 4",
    "Item 5",
    "Item 6",
];

function MyComponent(props) {
    return React.createElement(
        "ul",
        { className: "myClass" },
        props.myList.map((item,index) => React.createElement("li", {key:index}, item))
    );
}

ReactDOM.createRoot(document.getElementById('root')!).render(React.createElement(MyComponent, {myList:items}, null))

在这个例子中,MyComponent函数接收一个名为props的参数,这个参数是一个对象,包含了一个名为myList的属性。然后,MyComponent函数使用props.myList来创建<li>标签的子元素。

在React的学习过程中,我们首先接触到的可能是createElement函数。通过它,我们可以深入理解React如何工作,了解React是如何将JavaScript和DOM结合起来的。然而,作为React开发人员,我们并不总是直接使用createElement函数。毕竟,编写复杂、几乎不可读的JavaScript语法树并不是我们的目标。我们希望的是能够更高效、更直观地创建React元素。这就需要引入JSX。

JSX,或JavaScript XML,是一种JavaScript的扩展语法。它结合了JavaScript的逻辑处理能力和XML的标签语法,让我们可以直接在JavaScript代码中使用类似HTML的标签语法来定义React元素。这使得我们的代码更加直观、易读,也更接近我们熟悉的HTML编写方式。

尽管JSX看起来非常像HTML,但它们并不完全相同。JSX实际上是JavaScript的一部分,它只是提供了一种更直观、更易于编写的方式来创建React元素。这意味着,当我们在JSX中编写标签语法时,背后实际上还是通过React的createElement函数来创建元素的。

在下一章节中,我们讨论如何使用 JSX 构建 React 应用程序。

相关推荐
范文杰2 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪2 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪2 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy3 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom3 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom3 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom3 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom3 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom4 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试
LaoZhangAI4 小时前
2025最全GPT-4o图像生成API指南:官方接口配置+15个实用提示词【保姆级教程】
前端