Список статей с рендерингом JSX
В этой главе вы узнаете, как использовать выражения JSX для рендеринга данных JS в интерфейс, что позволит домашней странице блога отображать список карточек статей.
{} Встраивание выражений в JSX
В JSX,фигурные скобки {}являются точкой входа в мир JavaScript.
Любое JS-выражение можно поместить внутрь фигурных скобок: переменные, операции, вызовы функций, тернарные выражения и т. д.
Пример
const blogTitle = 'EXAMPLE Front-end Notes'
const author = 'Xiao Ming'
return (
<div>
<h1>{blogTitle}</h1>
<p>Автор:{author}</p>
<p>Текущее время:{new Date().toLocaleDateString()}</p>
<p>Приветственное сообщение:{author ?`Hello, ${author}` : 'Welcome, visitor'}</p>
</div>
)
}
Страница отобразит:
EXAMPLE 前端笔记 作者:小明 当前时间:2024/5/15 欢迎语:你好,小明
Фигурные скобки могут содержать тольковыражения(код, который вычисляется в значение), а не инструкции. Например,
{if (condition) ...}недопустимо, но{condition ? 'A' : 'B'}допустимо.
Привязка атрибутов
HTML-атрибуты в JSX нужно динамически привязывать с помощью фигурных скобок.
Пример
const coverUrl = '/images/react-cover.png'
const linkUrl = '/post/1'
return (
<div>
{/* Динамический атрибут: фигурные скобки привязывают переменную JS */}
<img src={coverUrl} alt="Обложка статьи" />
<a href={linkUrl}>Читать далее</a>
{/* Примечание: class должен быть записан как className */}
<div className="card active">Содержимое карточки</div>
{/* style принимает объект, имена свойств в camelCase */}
<div style={{ color: '#427DB8', fontSize: '16px' }}>
Зелёный текст
</div>
</div>
)
}
| HTML | JSX | Объяснение |
|---|---|---|
class="btn" | className="btn" | class — зарезервированное слово JS |
style="color: red" | style={{ color: 'red' }} | Принимает объект, имена свойств в camelCase |
src="xxx.html" | src={variable} | Динамические значения используют фигурные скобки |
onclick="fn()" | onClick={fn} | Имена событий в camelCase, передавайте ссылку на функцию |
Рендеринг списков: array.map()
В React нет директив, как в Vuev-forделает.
Чтобы отображать списки в JSX, напрямую используйте методarray.map()из JavaScript.
Пример
// Используйте массив объектов JS для имитации данных статьи
const articles = [
{
id: 1,
title: 'Полное руководство по началу работы с React',
summary: 'Изучите React Hooks с нуля, охватывая основные концепции, такие как useState, useEffect и многое другое.',
date: '2024-05-10',
category: 'React',
cover: '/images/react.png'
},
{
id: 2,
title: 'Подробное объяснение асинхронного программирования на JavaScript' 66) 'Разобраться с Promise, async/await, циклом событий и очередью микрозадач в одной статье.',
summary: 'Одна статья, чтобы полностью разобраться с Promise, async/await, циклом событий и очередью микрозадач.',
date: '2024-05-08',
category: 'JavaScript',
cover: '/images/js.png'
},
{
id: 3,
title: 'CSS Grid Layout на практике',
summary: 'Легко реализуйте сложные адаптивные макеты с помощью CSS Grid.',
date: '2024-05-05',
category: 'CSS',
cover: '/images/css.png'
}
]
return (
<div className="article-list">
{/* map перебирает массив, возвращая фрагмент JSX для каждого элемента */}
{articles.map(article => (
<div key={article.id} className="card">
<img src={article.cover} alt={article.title} />
<div className="card-body">
<span className="category">{article.category}</span>
<h3>{article.title}</h3>
<p>{article.summary}</p>
<span className="date">{article.date}</span>
</div>
</div>
))}
</div>
)
}
Важность атрибута key
key— уникальный идентификатор, присваиваемый каждому элементу списка, помогая React определять, какие элементы изменились.
Без key React использует стратегию «обновления на месте», что может вызвать путаницу состояния и снижение производительности.
| Значение key | Последствие |
|---|---|
| Уникальный id (рекомендуется) | Правильно отслеживает каждый элемент, эффективный Diff |
| Индекс массива | Вставка/удаление может привести к нарушению порядка содержимого поля ввода |
| Нет key | Предупреждение в консоли, плохая производительность |
Всегда добавляйтеуникальный и стабильныйkey к JSX, возвращаемому map. Не используйте index в качестве key, особенно когда элементы списка могут добавляться, удаляться или переупорядочиваться.
Условный рендеринг
В React нет v-if, но есть три способа реализовать условный рендеринг.
Пример
const articles = []
const isLoading = false
return (
<div>
{/* Способ 1: тернарное выражение — подходит для выбора между двумя */}
{isLoading ? (
<p>Загрузка, пожалуйста, подождите...</p>
) : (
<p>Загрузка завершена!</p>
)}
{/* Способ 2: && сокращённое вычисление — подходит для "показать, если условие истинно, не показывать, если нет" */}
{articles.length === 0 && <p>Пока нет статей, следите за обновлениями.</p>}
{/* Способ 3: if/else на верхнем уровне компонента — подходит для сложной логики с несколькими условиями */}
{articles.length > 0 ? (
<div>
{articles.map(a => <div key={a.id}>{a.title}</div>)}
</div>
) : (
<p>Нет данных</p>
)}
</div>
)
}
Сравнение трёх подходов к условному рендерингу
| Подход | Синтаксис | Применимый сценарий |
|---|---|---|
Тернарный оператор? : | {cond ? <A /> : <B />} | Выбрать одно из двух, обязательно что-то вернуть |
Сокращённое вычисление&& | {cond && <A />} | Показывать, если есть, не показывать, если нет |
| Ранняя проверка if | Сохранить JSX в переменной перед return | Сложные сценарии условного ветвления |
&&У сокращённого вычисления есть подводный камень: когда условие — число 0, рендерится "0". Рекомендуется, чтобы&&левая часть всегда была логическим значением:{list.length > 0 && ...}вместо{list.length && ...}。
Практика: Готовая главная страница блога
Пример
import './App.css'
function App() {
const articles = [
{
id: 1, title: 'Полное руководство по началу работы с React',
summary: 'Изучите React Hooks с нуля, охватывая основные концепции, такие как useState, useEffect и многое другое.',
date: '2024-05-10', category: 'React', cover: '/images/react.png'
},
{
id: 2, title: 'Подробное объяснение асинхронного программирования в JavaScript',
summary: 'Разобраться с Promise, async/await, циклом событий и очередью микрозадач в одной статье.',
date: '2024-05-08', category: 'JavaScript', cover: '/images/js.png'
},
{
id: 3, title: 'CSS Grid Layout на практике',
summary: 'Легко реализуйте сложные адаптивные макеты с помощью CSS Grid.',
date: '2024-05-05', category: 'CSS', cover: '/images/css.png'
}
]
return (
<div className="app">
<header className="navbar">
<h1 className="logo">ПРИМЕР Блог</h1>
<nav>
<a href="/">Главная</a>
<a href="#">О нас</a>
</nav>
</header>
<main className="container">
<h2 className="section-title">Последние статьи</h2>
{/* Условный рендеринг: показывать статьи, если они есть, иначе показывать пустое состояние */}
{articles.length === 0 ? (
<p className="empty-tip">Пока нет статей, следите за обновлениями.</p>
) : (
<div className="article-grid">
{/* Рендеринг списка: map перебирает элементы массива */}
{articles.map(article => (
<div key={article.id} className="article-card">
<img src={article.cover} alt={article.title} className="card-cover" />
<div className="card-content">
<span className="card-category">{article.category}</span>
<h3 className="card-title">{article.title}</h3>
<p className="card-summary">{article.summary}</p>
<span className="card-date">{article.date}</span>
</div>
</div>
))}
</div>
)}
</main>
<footer className="footer">
<p>© 2024 Пример блога. Работает на React.</p>
</footer>
</div>
)
}
export default App
Пример
.section-title {
font-size: 24px;
margin-bottom: 20px;
color: #333;
}
.article-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}
.article-card {
background: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
transition: transform 0.2s, box-shadow 0.2s;
cursor: pointer;
}
.article-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
.card-cover {
width: 100%;
height: 180px;
object-fit: cover;
}
.card-content {
padding: 16px;
}
.card-category {
display: inline-block;
padding: 2px 10px;
background: #e3f2fd;
color: #1976d2;
border-radius: 12px;
font-size: 12px;
margin-bottom: 8px;
}
.card-title {
font-size: 18px;
margin-bottom: 8px;
color: #222;
}
.card-summary {
font-size: 14px;
color: #666;
line-height: 1.6;
margin-bottom: 12px;
}
.card-date {
font-size: 12px;
color: #999;
}
.empty-tip {
text-align: center;
color: #999;
padding: 60px 0;
font-size: 16px;
}
Краткое содержание главы
В этой главе вы изучили четыре основные операции в JSX:{}Встраивание выражений, привязка атрибутов (className / style),map()Рендеринг списков + key, условный рендеринг (тернарный оператор / короткое замыкание).
На этом этапе главная страница блога может динамически отображать карточки статей на основе данных JS.
Дополнительные расширения