JSX
简介
在代码中同时包含 JS 和 HTML 标记,这种写法就是 React 的「模版语言」JSX。
JSX 并不是一个新的模版语言,而是一个语法糖,可以用 JS 的方式来实现。使用 React.createElement() 这个 API 来创建一个组件的实例。
例如:
import { useState } from 'react';
const App = () => {
const [count, setCount] = useState(0);
return (
<div>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>add</button>
</div>
);
};
export default App;
调用 createElement 创建一个 React 元素,具有 type
、 props
和 children
。
import { createElement, useState } from 'react';
const App = () => {
const [count, setCount] = useState(0);
return createElement(
'div',
null,
createElement('h1', null, count),
createElement(
'button',
{
onClick: function () {
return setCount(count + 1);
}
},
'add'
)
);
};
export default App;
在实际开发中,不推荐使用 React.createElement()
这种方式,在官方中也将其列入「旧版 API」中,使用 JSX 更简洁易读。
JSX 规则
- 返回单个根元素
- 所有标签要闭合
- 采用驼峰命名
将 HTML 转换为 JSX 的转换器:https://transform.tools/html-to-jsx
原理
浏览器无法直接理解 JSX,需要通过 Babel 和 TypeScript 转换为 JS。
Babel 编译,@babel/plugin-transform-react-jsx
老版本的 React 中,为什么写 jsx 的文件要默认引入 React?
import React from 'react';
function App() {
return <div>hello,world</div>;
}
因为 JSX 被 Babel 编译后,会变成 React.createElement()
形式,所以需要引入 React,防止找不到 React 引起报错。
为何要返回单个根元素?
在 React 中,组件的返回值必须是一个根元素。如下所示都是错误的:
function Foo() {
return (
<div>1</div>
<div>2</div>
)
}
function Bar() {
return (
<div>
{isOpen && (
<div>1</div>
<div>2</div>
)}
</div>
)
}
前面说了,JSX 是 React.createElement()
的语法糖。Babel 会将 Foo 组件转换为下面这样:
function Foo() {
return React.createElement('div', null, '1')
React.createElement('div', null, '2');
}
这里试图返回两个东西,这不符合 JS 语法。
注释
在 JSX 中写注释不能单独使用//
,需要这么写 {/* 注释 */}
htmlFor
label
标签不能使用for
,要用htmlFor
<label htmlFor="zgh"></label>
className
为了防止和 js 中的class
类名冲突,需要将class
写成className
,小驼峰命名
<input className="input" />
循环遍历
JSX 中默认对数组进行 join()
操作,如下代码会在页面上显示“abc”
function List() {
const arr = ['a', 'b', 'c'];
return <div>{arr}</div>;
}
利用原生 js 写法,使用 map
遍历数组,因为 map 有返回值,不能使用 forEach
。
在 map 方法中 的元素需要设置 key
属性,key 最好是唯一的字符串,没得选只能用元素索引 index,但是这样做会导致性能变差,还可能引起组件状态的问题
function List() {
const arr = ['a', 'b', 'c'];
return (
<>
<ul>
{arr.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</>
);
}
也可以把遍历的逻辑抽离出来
const arr = ['a', 'b', 'c'];
function Li() {
return arr.map((item, index) => <li key={index}>{item}</li>);
}
function List() {
return (
<>
<ul>
<Li />
</ul>
</>
);
}
条件判断
- 条件语句:if、switch
- 三元运算符
- 逻辑运算符:
&&
、||
、!
在 JSX 的大括号中不会渲染的值:布尔值、空字符、null、undefined、对象、函数
{0 && <div>react</div>}