React.js. Элементы и компоненты

21.07.2021

Теги: DOMFrontendHTMLJavaScriptReact.jsWeb-разработкаКлассКомпонентФункция

React-элемент

Если говорить простыми словами, React-элемент описывает то, что должно появиться на экране. А если не простыми, то React-элемент описывает узел DOM в виде javascript-объекта. Обратите внимание на слово «описывает». React-элемент — это не то, что будет на экране, а описание того, что будет на экране. Для этого есть две причины:

  1. JavaScript-объекты лёгкие и React может создавать и уничтожать их без особых затрат
  2. React может сравнивать объекты и настоящие DOM-узлы — и точечно обновлять DOM

Для того, чтобы создать объект, который описывает DOM-узел (он же React-элемент), можно воспользоваться методом

const element = React.createElement(
    "div", // тип этого элемента
    {id: "login"}, // свойства этого элемента
    "Войти" // содержимое (строка или массив дочерних элементов)
);

Аргументом type может быть строка, содержащая имя тега (например, div или span), React-компонент (класс или функция) или React-фрагмент. Когда аргументом type является строка — это фактически означает обращение к встроенному React-элементу div, span, em, strong и так далее.

Переменная element из кода выше содержит теперь объект:

{
    type: "div",
    props: {
        id: "login",
        children: "Войти"
    }
}

Когда этот объект будет отображён в DOM с помощью ReactDOM.render(), получим новый DOM-узел:

<div id="login">Войти</div>

React-компонент

При изучении React первое, чему учат — это компоненты. Потом туда приплетают React-элементы, причем оба термина часто путают. React-компонент — это функция или класс, который принимает входные данные (опционально) и возвращает React-элемент — то есть, javascript-объект.

function Button(props) {
    return React.createElement(
        "div",
        {id: "login", onClick: props.onLogin},
        "Войти"
    )
}

До этого момента мы создавали элементы на основе встроенных React-элементов (div, span и т.д.), но мы также можем передавать другие React-компоненты в качестве первого аргумента функции createElement().

const element = React.createElement(
    User,
    {name: "Вася"},
    null
)

Если React увидит класс или функцию в качестве первого аргумента (вместо div или span) — он проверит, какой элемент будет отображаться на самом деле. React будет рекурсивно продолжать делать это, пока не построит полный javascript-объект представления компонента User.

function Button(props) {
    return React.createElement("button", {className: "btn"}, props.text);
}

function User(props) {
    return React.createElement(
        "div",
        null,
        [
            React.createElement("span", null, props.userName),
            React.createElement(Button, {text: props.buttonText})
        ]
    );
}

ReactDOM.render(
    React.createElement(User, {userName: "Вася", buttonText: "Кнопка"}),
    document.getElementById("root")
);

Очень упрощенно можно сказать, что этот объект выглядит примерно так:

{
    type: "div",
    props: {
        children: [
            {
                type: "span",
                props: {
                    children: "Вася"
                }
            },
            {
                type: "button",
                props: {
                    className: "btn",
                    children: "Кнопка"
                }
            }
        ]
    }
}

Теперь можно сравнить этот объект с реальным DOM-узлом и внести точечные изменения, чтобы в браузере все было точь-в-точь, как в виртуальной модели компонента User.

<div id="root">
    <div>
        <span>Вася</span>
        <button class="btn">Кнопка</button>
    </div>
</div>

Функциональные и классовые компоненты

Проще всего объявить React-компонент как функцию:

function Hello(props) {
    return React.createElement("div", null, `Привет, ${props.name}`);
}

ReactDOM.render(
    React.createElement(Hello, {name: "Вася"}, null),
    document.getElementById("root")
);

Ещё компоненты можно определять как классы ES6:

class Hello extends React.Component {
    render() {
        return React.createElement("div", null, `Привет, ${this.props.name}`);
    }
}

ReactDOM.render(
    React.createElement(Hello, {name: "Вася"}, null),
    document.getElementById("root")
);

С точки зрения React, эти два компонента эквивалентны.

Поиск: DOM • HTML • JavaScript • React.js • Web-разработка • Frontend • Класс • Компонент • Функция

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.