Skip to content

3 JSX

3.1 问题

对于开发者来说,通过 createElement 方法构建用户界面属实不太友好,但是在 React 内部确实需要通过这个方法创建虚拟DOM对象,如何解决这个矛盾呢?

React 为 createElement 方法创造了替代语法,让开发者可以通过类似于 HTML的语法创建用户界面,在构建应用时,再使用 babel将这种替换语法转换回 createElement 方法的调用代码。

const button = <button type="button">button</button>
React.createElement('button', {type: "button"}, "button")

<button type="button">button</button> = React.createElement('button', {type: "button"}, "button")

3.2 JSX是什么?

JSX is a syntax extension of the JavaScript programming language, created by Facebook to simplify the code for creating elements. In React, JSX is commonly used to build user interfaces.

const button = <button>save</button>
ReactDOM.render(button, document.getElementById("root"))

但是这种语法浏览器是不识别的,所以我们需要借助 Babel 对其进行转换,将其转换为 React.createElement 方法的调用

<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.13.17/babel.min.js"></script>

所以说JSX的本质就是 JavaScript,虽然它看起来很像 HTML,通过 Babel REPL 环境验证代码的转换。

Babel 是一个广泛使用的 JavaScript 编译器(transpiler),其主要功能是将现代 JavaScript 代码(例如 ES6+ 或 JSX)转换为向后兼容的 JavaScript 代码,使其可以在所有主流浏览器中运行。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="root"></div>
    <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.13.17/babel.min.js"></script>
    <script type="text/babel">
        const button = <button>Click Me</button>;
        ReactDOM.render(button, document.getElementById("root"));
    </script>
</body>
</html>

type="text/babel" 是在 HTML 中指定脚本类型的一种方式,用于告诉浏览器,这段代码需要通过 Babel 编译器来处理。

Screenshot 2025-01-24 at 23.48.54

Screenshot 2025-01-24 at 23.49.21

3.3 初体验

需求:使用 JSX 语法创建嵌套 HTML 结构

<main id="main">
  <h1>My Blog</h1>
  <article>
    <h2>My First Article</h2>
    <p class="text">This is the content of the article</p>
  </article>
</main>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="root"></div>
    <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.13.17/babel.min.js"></script>
    <script type="text/babel">
        const jsx = <main id="main">
            <h1>My Blog</h1>
            <article>
                <h2>My First Article</h2>
                <p className="text">This is the content of the article</p>
            </article>
        </main>
        ReactDOM.render(jsx, document.getElementById("root"));
    </script>

</html>

Screenshot 2025-01-25 at 00.12.29

Screenshot 2025-01-25 at 00.12.39

3.4 JSX and HTML

  1. 在使用JSX语法创建元素时,最外层必须要有一个根标记

根标记(Root Tag)是 HTML 文档中的一个元素,用作 React 应用程序的挂载点,也就是 React 应用程序将其 UI 渲染到网页上的起点。

根标记是 HTML 中用作 React 应用挂载点的元素,一般是标准的 HTML 元素。理论上,任何 HTML 元素都可以作为根标记,但通常使用一些通用的标记来作为根标记,以便组织和渲染 React 应用。

// 错误写法
const jsx = (
 <p>Hello</ p>
 <p>world</p>
)
// 正确写法
const jsx = (
 <div>
     <p>Hello</p>
    <p>world</p>
 </div>
)

为避免因为要满足规定而出现无意义标记,React 提供了占位符标记,占位符标记在渲染后不会产生真实 DOM对象

// 使用占位符标记充当根元素
// 避免渲染结果出现无意义标记
const jsx = (
  <React.Fragment>
     <p>Hello</p>
    <p>world</p>
  </React.Fragment>
)
// 使用占位符标记的简写语法
const jsx = (
  <>
     <p>Hello</p>
    <p>world</p>
  </>
)

Screenshot 2025-01-25 at 00.35.30

Screenshot 2025-01-25 at 00.35.36

  1. 单标记必须闭合
<input type="text"/>
<img src="" alt="" />

Screenshot 2025-01-25 at 00.42.47

Screenshot 2025-01-25 at 00.42.56

  1. 属性名称遵循驼峰式命名法(小驼峰)
<!—— HTML 写法 </!——>
<input maxlength="10" readonly autofoucs>
// JSX 写法
<input maxLength="10" readOnly autoFocus />

Screenshot 2025-01-25 at 00.45.30

Screenshot 2025-01-25 at 00.45.40

  1. 添加类名使用className 属性,因为 class 在 Javascript 中是保留关键字

     <!—— HTML 写法 ——>
     <input class="todos">
    
    // JSX 写法
    <input className="todos" />
    
  2. label 使用 htmlFor 属性,因为 for 在 JavaScript 中是保留关键字

    <!--- HTML 写法 --->
    <label for="demo">This is a test input</label>
    
    // JSX 写法
    <label htmlFor="demo">This is a test input</label>
    

    Screenshot 2025-01-25 at 00.56.03

    Screenshot 2025-01-25 at 00.56.12

3.5 Interpolation Syntax

在JSX中可以使用插值语法将动态数据插入到指定位置。

  1. 插入文本
const someClass = "some-class"
const someText = "I am interpolating text"
const text_jsx = <p className={someClass}>{someText}</p>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="root"></div>
    <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.13.17/babel.min.js"></script>
    <script type="text/babel">
        const someClass = "some-class";
        const someText = "I am interested in React";
        const jsx = (
            <>
                <p className={someClass}>{someText}</p>
            </>
        );
        ReactDOM.render(jsx, document.getElementById("root"));
    </script>

</html>

Screenshot 2025-01-25 at 01.14.57

Screenshot 2025-01-25 at 01.15.04

  1. 计算
const x = 10
const y = 20
const paragraph = <p>{x * y}</p> 
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="root"></div>
    <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.13.17/babel.min.js"></script>
    <script type="text/babel">
        const n = 10;
        const m = 20;
        const jsx = (
            <>
                <p>{n + m}</p>
            </>
        );
        ReactDOM.render(jsx, document.getElementById("root"));
    </script>

</html>

Screenshot 2025-01-25 at 01.17.08

Screenshot 2025-01-25 at 01.16.57

  1. 函数调用
function getValue() {
 return "some value from getValue function"
}
const text = <p>{getValue()}</p>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="root"></div>
    <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.13.17/babel.min.js"></script>
    <script type="text/babel">
        function getValue() {
            return "I am interested in React";
        }
        const jsx = (
            <>
                <p>{getValue()}</p>
            </>
        );
        ReactDOM.render(jsx, document.getElementById("root"));
    </script>

</html>

Screenshot 2025-01-25 at 01.22.12

Screenshot 2025-01-25 at 01.22.21