React.js. Элементы и компоненты
21.07.2021
Теги: DOM • Frontend • HTML • JavaScript • React.js • Web-разработка • Класс • Компонент • Функция
React-элемент
Если говорить простыми словами, React-элемент описывает то, что должно появиться на экране. А если не простыми, то React-элемент описывает узел DOM в виде javascript-объекта. Обратите внимание на слово «описывает». React-элемент — это не то, что будет на экране, а описание того, что будет на экране. Для этого есть две причины:
- JavaScript-объекты лёгкие и React может создавать и уничтожать их без особых затрат
- 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 • Класс • Компонент • Функция