React JSX
JSX (JavaScript XML) — это расширение синтаксиса JavaScript, которое выглядит как XML. В React его часто используют вместо обычного JavaScript для написания UI-компонентов, что позволяет описывать структуру и поведение компонентов HTML-подобным способом.
Использование JSX не обязательно, но у него есть следующие ключевые преимущества:
- Эффективное выполнение: после компиляции в код JavaScript он оптимизируется и работает быстрее;
- Типобезопасность: ошибки можно обнаружить на этапе компиляции (что ещё лучше с TypeScript);
- Удобное написание: структура UI интуитивно понятна и ясна, встраивание выражений JavaScript более гибкое, а написание шаблонов простое и быстрое;
- Суть: это не строка/HTML; Babel (встроенный в Vite) компилирует это в вызовы React.createElement.
Давайте сначала посмотрим на следующий код:
const element = <h1>Hello, world!</h1>;
Этот кажущийся странным синтаксис тегов не является ни строкой, ни HTML.
Он называется JSX — синтаксическое расширение JavaScript. Мы рекомендуем использовать JSX в React для описания пользовательских интерфейсов.
JSX реализован внутри JavaScript.
Мы знаем, что элементы — это наименьшие единицы, из которых состоит приложение React, а JSX используется для объявления элементов в React.
В отличие от элементов DOM браузера, элементы в React на самом деле являются обычными объектами. React DOM гарантирует, что содержимое данных DOM браузера остаётся согласованным с элементами React.
Чтобы отобразить элементы React в корневой DOM-узел, мы передаём их все в ReactDOM.render() для отображения на странице:
Пример React
Попробуйте »
Примечание:
Поскольку JSX — это JavaScript, некоторые идентификаторы, такие как
classиforне рекомендуются в качестве XMLclassNameиhtmlForимён атрибутов. Вместо этого React DOM использует
Правила синтаксиса JSX
Правила синтаксиса JSX
JSX выглядит как HTML, но имеет строгие правила:
- HTML может<br>, но JSX должен<br />(самозакрывающийся).
- Все теги должны быть закрыты:<div></div>。
class → className:
Поскольку class — это ключевое слово JavaScript, вместо него используйте className.
<div className="container">内容</div>
htmlFor (внутри label):
<label for="id"> → <label htmlFor="id">
Компоненты, начинающиеся с заглавной буквы:
Пользовательские компоненты должны начинаться с заглавной буквы (строчные будут восприниматься как HTML-теги).
<Card /> {/* 正确,自定义组件 */}
<card /> {/* 错误,会被当成 <card> HTML 标签 */}
Комментарии:
используйте{/* comment content */}。
jsx{/* 这是一个 JSX 注释 */}
Корневой элемент:
return может иметь только один корневой узел.
return (
<> {/* 碎片 Fragment,空标签,不渲染 DOM */}
<h1>标题</h1>
<p>段落</p>
</>
);
Мы можем открыть src/App.jsx и изменить return на:
return (
<>
<h1 className="title">JSX 语法规则演示</h1>
<img src="../vite.svg.html" alt="Vite Logo" />
<br />
{/* 自闭合标签和注释 */}
<p>注意 className 和闭合标签</p>
</>
);Сохраните, чтобы увидеть эффект.
Встраивание выражений, условный рендеринг, рендеринг списков
Самая мощная особенность JSX в том, что с помощью {} можно встраивать JavaScript-выражения (только выражения, а не инструкции вроде if/for).
Встраивание выражений
Любое допустимое JS-выражение можно поместить внутрь{}:
const name = 'example';
const now = new Date().toLocaleString();
return (
<div>
<h1>你好,{name}!</h1>
<p>当前时间:{now}</p>
<p>计算结果:{2 + 3 * 5}</p> {/* 17 */}
</div>
);
Условный рендеринг
Используйте тернарные операторы или&&:
const isLoggedIn = true;
const count = 0;
return (
<div>
{isLoggedIn ? <h1>欢迎回来,{name}!</h1> : <h1>请登录</h1>}
{count > 0 && <p>你有 {count} 条未读消息</p>} {/* count 为 0 时不渲染 */}
</div>
);
Избегайте:Не используйте операторы if напрямую в JSX (их можно использовать внутри тел функций).
Рендеринг списков (важность key)
Используйте map() для рендеринга массивов. Необходимо добавить атрибут key каждому элементу (уникальный идентификатор, который помогает React эффективно обновлять DOM).
const items = [
{ id: 1, name: '苹果' },
{ id: 2, name: '香蕉' },
{ id: 3, name: '橙子' },
];
return (
<ul>
{items.map(item => (
<li key={item.id}> {/* key 必须唯一且稳定! */}
{item.name}
</li>
))}
</ul>
);Важность key:
- Без key: React выдаст предупреждение, что может вызвать ошибки рендеринга (особенно когда список изменяется динамически).
- Плохая привычка: использовать index в качестве key (key={index}) — когда порядок списка меняется, это может вызвать ненужные повторные рендеры или потерю состояния.
- Лучшая практика: использовать уникальный ID из данных (например, id из базы данных).
Стилизация
В React есть несколько подходов к стилизации; давайте сначала изучим два самых базовых.
Встроенные стили
Используйте атрибут style, значение которого — объект (camelCase):
return (
<div
style={{
backgroundColor: '#F0F0F0',
padding: '20px',
borderRadius: '8px',
textAlign: 'center',
fontFamily: 'Arial, sans-serif',
}}
>
<h2 style={{ color: 'blue', marginBottom: '10px' }}>
内联样式示例
</h2>
</div>
); - Преимущество: динамические стили просты (можно использовать переменные).
- Недостаток: неудобно поддерживать сложные стили.
CSS Modules (рекомендуется, локальная изоляция)
Vite поддерживает CSS Modules по умолчанию, избегая глобального загрязнения.
Создайте src/App.css (уже существует) или новый файл src/styles/Card.module.css:
/* Card.module.css */
.card {
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
padding: 20px;
margin: 20px;
}
.title {
color: #333;
margin: 0 0 10px 0;
}
.content {
color: #666;
}Импортируйте и используйте его в компоненте (имена классов с локальной областью видимости генерируются автоматически):
import styles from './styles/Card.module.css';
return (
<div className={styles.card}>
<h3 className={styles.title}>标题</h3>
<p className={styles.content}>内容</p>
</div>
);
- Преимущество: имена классов автоматически хешируются (например, .card__abc123), поэтому конфликтов не возникает.
Полная практика:Измените предыдущий компонент Card, чтобы он использовал CSS Modules.
Создайте src/components/Card.module.css:
.container {
width: 300px;
border: 1px solid #ccc;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
background: white;
}
.image {
width: 100%;
height: 200px;
object-fit: cover;
}
.title {
margin: 0 0 10px 0;
padding: 20px 20px 0;
color: #333;
}
.content {
padding: 0 20px 20px;
color: #666;
}Измените Card.jsx:
import styles from './Card.module.css';
const Card = ({ title, content, imageUrl }) => {
return (
<div className={styles.container}>
{imageUrl && <img src={imageUrl} alt={title} className={styles.image} />}
<h3 className={styles.title}>{title}</h3>
<p className={styles.content}>{content}</p>
</div>
);
};
export default Card;
Использование JSX
JSX выглядит похоже на HTML; можно посмотреть пример:
Мы можем вложить несколько HTML-тегов в приведённый выше код, и их нужно обернуть элементом div. У элемента p в примере есть пользовательский атрибутdata-myattribute, чтобы добавить пользовательские атрибуты, нужно использоватьdata-префикс.
Пример React
Попробуйте »
Отдельный файл
Ваш код React JSX можно разместить в отдельном файле, например, мы создаёмhelloworld_react.jsфайл, код выглядит следующим образом:
Затем подключите JS-файл к HTML-файлу:
Пример React
Попробуйте »
Выражения JavaScript
Мы можем использовать выражения JavaScript в JSX. Выражения записываются в фигурных скобках{}внутри. Пример выглядит так:
Пример React
Попробуйте »
В JSX нельзя использоватьif elseинструкции, но можно использоватьусловное (тернарная операция)выражение вместо этого. В следующем примере, если переменнаяiравна1браузер выведетtrue, если значение i изменить, он выведетfalse.
Пример React
Попробуйте »
Стили
React рекомендует использовать встроенные стили. Мы можем использоватьcamelCaseсинтаксис для задания встроенных стилей. React автоматически добавит после указанного числа элементаpx. Следующий пример демонстрирует дляh1элемента добавлениеmyStyleвстроенного стиля:
Пример React
Попробуйте »
Комментарии
Комментарии нужно писать в фигурных скобках, например:
Пример React
Попробуйте »
Массивы
JSX позволяет вставлять массивы в шаблоны, и массив автоматически разворачивает все элементы:
Пример React
Попробуйте »