3 JSX
3.1 问题
对于开发者来说,通过 createElement
方法构建用户界面属实不太友好,但是在 React 内部确实需要通过这个方法创建虚拟DOM对象,如何解决这个矛盾呢?
React 为 createElement
方法创造了替代语法,让开发者可以通过类似于 HTML的语法创建用户界面,在构建应用时,再使用 babel将这种替换语法转换回 createElement 方法的调用代码。
<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.
但是这种语法浏览器是不识别的,所以我们需要借助 Babel 对其进行转换,将其转换为 React.createElement
方法的调用
所以说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 编译器来处理。
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>
3.4 JSX and HTML
- 在使用JSX语法创建元素时,最外层必须要有一个根标记
根标记(Root Tag)是 HTML 文档中的一个元素,用作 React 应用程序的挂载点,也就是 React 应用程序将其 UI 渲染到网页上的起点。
根标记是 HTML 中用作 React 应用挂载点的元素,一般是标准的 HTML 元素。理论上,任何 HTML 元素都可以作为根标记,但通常使用一些通用的标记来作为根标记,以便组织和渲染 React 应用。
为避免因为要满足规定而出现无意义标记,React 提供了占位符标记,占位符标记在渲染后不会产生真实 DOM对象
// 使用占位符标记充当根元素
// 避免渲染结果出现无意义标记
const jsx = (
<React.Fragment>
<p>Hello</p>
<p>world</p>
</React.Fragment>
)
- 单标记必须闭合
- 属性名称遵循驼峰式命名法(小驼峰)
-
添加类名使用className 属性,因为 class 在 Javascript 中是保留关键字
-
label 使用 htmlFor 属性,因为 for 在 JavaScript 中是保留关键字
3.5 Interpolation Syntax
在JSX中可以使用插值语法将动态数据插入到指定位置。
- 插入文本
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>
- 计算
<!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>
- 函数调用
<!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>