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 应用程序。

相关推荐
Myli_ing7 分钟前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风10 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
软件小伟19 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾40 分钟前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧1 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep7011 小时前
第8章利用CSS制作导航菜单
前端·css
hummhumm1 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
幼儿园的小霸王2 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue
疯狂的沙粒2 小时前
对 TypeScript 中高级类型的理解?应该在哪些方面可以更好的使用!
前端·javascript·typescript