Перейти к содержанию

Разработка интерфейса

React — это библиотека JavaScript для визуализации пользовательских интерфейсов (UI). Пользовательский интерфейс строится из небольших блоков, таких как кнопки, текст и изображения. React позволяет объединять их в многократно используемые, вложенные компоненты. От веб-сайтов до приложений для телефонов — все на экране может быть разбито на компоненты. В этой главе вы научитесь создавать, настраивать и условно отображать компоненты React.

Ваш первый компонент

Приложения React строятся из изолированных частей пользовательского интерфейса, называемых компонентами. Компонент React — это функция JavaScript, которую вы можете посыпать разметкой. Компоненты могут быть как маленькими, как кнопка, так и большими, как целая страница. Вот компонент Gallery, отображающий три компонента Profile:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function Profile() {
    return (
        <img
            src="https://i.imgur.com/MK3eW3As.jpg"
            alt="Katherine Johnson"
        />
    );
}

export default function Gallery() {
    return (
        <section>
            <h1>Amazing scientists</h1>
            <Profile />
            <Profile />
            <Profile />
        </section>
    );
}

Готовы изучить эту тему?

Прочитайте Ваш первый компонент, чтобы узнать, как объявлять и использовать компоненты React.

Импорт и экспорт компонентов

Вы можете объявить много компонентов в одном файле, но в больших файлах может быть трудно ориентироваться. Чтобы решить эту проблему, вы можете экспортировать компонент в свой собственный файл, а затем импортировать этот компонент из другого файла:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import Profile from './Profile.js';

export default function Gallery() {
    return (
        <section>
            <h1>Amazing scientists</h1>
            <Profile />
            <Profile />
            <Profile />
        </section>
    );
}
1
2
3
4
5
6
7
8
export default function Profile() {
    return (
        <img
            src="https://i.imgur.com/QIrZWGIs.jpg"
            alt="Alan L. Hart"
        />
    );
}

Готовы изучить эту тему?

Прочитайте Импорт и экспорт компонентов, чтобы узнать, как разделить компоненты на собственные файлы.

Написание разметки с помощью JSX

Каждый компонент React — это функция JavaScript, которая может содержать некоторую разметку, которую React отображает в браузере. Компоненты React используют расширение синтаксиса под названием JSX для представления этой разметки. JSX очень похож на HTML, но он немного строже и может отображать динамическую информацию.

Если мы вставим существующую HTML-разметку в компонент React, она не будет работать:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
export default function TodoList() {
return (
    // This doesn't quite work!
    <h1>Hedy Lamarr's Todos</h1>
    <img
    src="https://i.imgur.com/yXOvdOSs.jpg"
    alt="Hedy Lamarr"
    class="photo"
    >
    <ul>
    <li>Invent new traffic lights
    <li>Rehearse a movie scene
    <li>Improve spectrum technology
    </ul>
);
}

Если у вас есть HTML, подобный этому, вы можете исправить его с помощью конвертера:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
export default function TodoList() {
    return (
        <>
            <h1>Hedy Lamarr's Todos</h1>
            <img
                src="https://i.imgur.com/yXOvdOSs.jpg"
                alt="Hedy Lamarr"
                className="photo"
            />
            <ul>
                <li>Invent new traffic lights</li>
                <li>Rehearse a movie scene</li>
                <li>Improve spectrum technology</li>
            </ul>
        </>
    );
}

Готовы изучить эту тему?

Прочитайте Writing Markup with JSX, чтобы узнать, как писать правильный JSX.

JavaScript в JSX с фигурными скобками

JSX позволяет вам писать HTML-подобную разметку внутри JavaScript-файла, сохраняя логику рендеринга и содержимое в одном месте. Иногда вы захотите добавить немного логики JavaScript или сослаться на динамическое свойство внутри этой разметки. В этой ситуации вы можете использовать фигурные скобки в JSX, чтобы "открыть окно" в JavaScript:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const person = {
    name: 'Gregorio Y. Zara',
    theme: {
        backgroundColor: 'black',
        color: 'pink',
    },
};

export default function TodoList() {
    return (
        <div style={person.theme}>
            <h1>{person.name}'s Todos</h1>
            <img
                className="avatar"
                src="https://i.imgur.com/7vQD0fPs.jpg"
                alt="Gregorio Y. Zara"
            />
            <ul>
                <li>Improve the videophone</li>
                <li>Prepare aeronautics lectures</li>
                <li>Work on the alcohol-fuelled engine</li>
            </ul>
        </div>
    );
}

Готовы изучить эту тему?

Читайте JavaScript в JSX с фигурными скобками, чтобы узнать, как получить доступ к данным JavaScript из JSX.

Передача пропсов компоненту

Компоненты React используют props для взаимодействия друг с другом. Каждый родительский компонент может передавать некоторую информацию своим дочерним компонентам, передавая им пропсы. пропсы могут напомнить вам атрибуты HTML, но вы можете передавать через них любые значения JavaScript, включая объекты, массивы, функции и даже JSX!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { getImageUrl } from './utils.js';

export default function Profile() {
    return (
        <Card>
            <Avatar
                size={100}
                person={{
                    name: 'Katsuko Saruhashi',
                    imageId: 'YfeOqp2',
                }}
            />
        </Card>
    );
}

function Avatar({ person, size }) {
    return (
        <img
            className="avatar"
            src={getImageUrl(person)}
            alt={person.name}
            width={size}
            height={size}
        />
    );
}

function Card({ children }) {
    return <div className="card">{children}</div>;
}
1
2
3
4
5
6
7
8
export function getImageUrl(person, size = 's') {
    return (
        'https://i.imgur.com/' +
        person.imageId +
        size +
        '.jpg'
    );
}

Готовы изучить эту тему?

Прочитайте Передача пропсов компоненту, чтобы узнать, как передавать и читать пропсы.

Условный рендеринг

Ваши компоненты часто должны отображать разные вещи в зависимости от различных условий. В React вы можете условно отображать JSX, используя синтаксис JavaScript, такой как операторы if, && и ? :.

В этом примере оператор JavaScript && используется для условного отображения галочки:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function Item({ name, isPacked }) {
    return (
        <li className="item">
            {name} {isPacked && '✔'}
        </li>
    );
}

export default function PackingList() {
    return (
        <section>
            <h1>Sally Ride's Packing List</h1>
            <ul>
                <Item isPacked={true} name="Space suit" />
                <Item
                    isPacked={true}
                    name="Helmet with a golden leaf"
                />
                <Item
                    isPacked={false}
                    name="Photo of Tam"
                />
            </ul>
        </section>
    );
}

Готовы изучить эту тему?

Прочитайте Условный рендеринг, чтобы узнать о различных способах условного рендеринга контента.

Рендеринг списков

Часто требуется отобразить несколько одинаковых компонентов из коллекции данных. Вы можете использовать JavaScript filter() и map() в React для фильтрации и преобразования массива данных в массив компонентов.

Для каждого элемента массива необходимо указать ключ. Обычно в качестве ключа используется идентификатор из базы данных. Ключи позволяют React отслеживать место каждого элемента в списке, даже если список меняется.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { people } from './data.js';
import { getImageUrl } from './utils.js';

export default function List() {
    const listItems = people.map((person) => (
        <li key={person.id}>
            <img
                src={getImageUrl(person)}
                alt={person.name}
            />
            <p>
                <b>{person.name}:</b>
                {' ' + person.profession + ' '}
                known for {person.accomplishment}
            </p>
        </li>
    ));
    return (
        <article>
            <h1>Scientists</h1>
            <ul>{listItems}</ul>
        </article>
    );
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
export const people = [
    {
        id: 0,
        name: 'Creola Katherine Johnson',
        profession: 'mathematician',
        accomplishment: 'spaceflight calculations',
        imageId: 'MK3eW3A',
    },
    {
        id: 1,
        name: 'Mario José Molina-Pasquel Henríquez',
        profession: 'chemist',
        accomplishment: 'discovery of Arctic ozone hole',
        imageId: 'mynHUSa',
    },
    {
        id: 2,
        name: 'Mohammad Abdus Salam',
        profession: 'physicist',
        accomplishment: 'electromagnetism theory',
        imageId: 'bE7W1ji',
    },
    {
        id: 3,
        name: 'Percy Lavon Julian',
        profession: 'chemist',
        accomplishment:
            'pioneering cortisone drugs, steroids and birth control pills',
        imageId: 'IOjWm71',
    },
    {
        id: 4,
        name: 'Subrahmanyan Chandrasekhar',
        profession: 'astrophysicist',
        accomplishment:
            'white dwarf star mass calculations',
        imageId: 'lrWQx8l',
    },
];
1
2
3
4
5
export function getImageUrl(person) {
    return (
        'https://i.imgur.com/' + person.imageId + 's.jpg'
    );
}

Готовы изучить эту тему?

Прочитайте Rendering Lists, чтобы узнать, как отобразить список компонентов и как выбрать ключ.

Соблюдение чистоты компонентов

Некоторые функции JavaScript являются чистыми. Чистая функция:

  • занимается своими делами. Она не изменяет никаких объектов или переменных, которые существовали до ее вызова.
  • Одинаковые входные данные, одинаковый выход. При одинаковых входных данных чистая функция всегда должна возвращать один и тот же результат.

Если вы будете писать свои компоненты только как чистые функции, вы сможете избежать целого класса непонятных ошибок и непредсказуемого поведения по мере роста вашей кодовой базы. Вот пример нечистого компонента:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
let guest = 0;

function Cup() {
    // Bad: changing a preexisting variable!
    guest = guest + 1;
    return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
    return (
        <>
            <Cup />
            <Cup />
            <Cup />
        </>
    );
}

Вы можете сделать этот компонент чистым, передав ему параметр вместо изменения предварительно существующей переменной:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function Cup({ guest }) {
    return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
    return (
        <>
            <Cup guest={1} />
            <Cup guest={2} />
            <Cup guest={3} />
        </>
    );
}

Готовы изучить эту тему?

Прочитайте Keeping Components Pure, чтобы узнать, как писать компоненты как чистые, предсказуемые функции.

Ваш UI как дерево

React использует деревья для моделирования отношений между компонентами и модулями.

Дерево рендеринга React - это представление родительских и дочерних отношений между компонентами.

Древовидный граф с пятью узлами, каждый из которых представляет компонент. Корневой узел расположен в верхней части древовидного графа и обозначен как "Корневой компонент". От него вниз отходят две стрелки, ведущие к двум узлам с метками "Компонент A" и "Компонент C". Каждая из стрелок помечена символом 'renders'. У 'Component A' есть одна стрелка 'renders' к узлу с меткой 'Component B'. У компонента C есть единственная стрелка 'renders' к узлу с меткой 'Component D'.

Пример дерева рендеринга React.

Компоненты, расположенные в верхней части дерева, рядом с корневым компонентом, считаются компонентами верхнего уровня. Компоненты, не имеющие дочерних компонентов, являются листовыми компонентами. Такое распределение компонентов по категориям полезно для понимания потока данных и производительности рендеринга.

Моделирование отношений между модулями JavaScript - еще один полезный способ понять работу приложения. Мы называем это деревом зависимостей модулей.

Древовидный граф с пятью узлами. Каждый узел представляет собой модуль JavaScript. Самый верхний узел обозначен как 'RootModule.js'. От него отходят три стрелки к узлам: 'ModuleA.js', 'ModuleB.js' и 'ModuleC.js'. Каждая стрелка обозначена как 'imports'. Узел 'ModuleC.js' имеет единственную стрелку 'imports', которая указывает на узел с меткой 'ModuleD.js'.

Пример дерева зависимостей модулей.

Дерево зависимостей часто используется инструментами сборки для компоновки всего необходимого JavaScript-кода для загрузки и рендеринга клиентом. Большой размер пакета ухудшает пользовательский опыт в React-приложениях. Понимание дерева зависимостей модулей помогает отлаживать такие проблемы.

Готовы изучить эту тему?

Прочитайте Ваш пользовательский интерфейс в виде дерева, чтобы узнать, как создавать деревья зависимостей рендеринга и модулей для приложения React и как они являются полезными ментальными моделями для улучшения пользовательского опыта и производительности.

Что дальше?

Перейдите по ссылке Ваш первый компонент, чтобы начать читать эту главу страница за страницей!

Или, если вы уже знакомы с этими темами, почему бы не прочитать Добаление интерактивности?

Источник — https://react.dev/learn/describing-the-ui

Комментарии