diff --git a/docs/docs/04-multiple-components.ru-RU.md b/docs/docs/04-multiple-components.ru-RU.md new file mode 100644 index 0000000000000..8007b55b3096f --- /dev/null +++ b/docs/docs/04-multiple-components.ru-RU.md @@ -0,0 +1,182 @@ +--- +id: multiple-components +title: Составные компоненты +permalink: multiple-components-ru-RU.html +prev: interactivity-and-dynamic-uis-ru-RU.html +next: reusable-components.html +--- + +Мы разобрались как создавать компоненты для отображения данных и подробно рассмотрели как происходит обработка действий пользователя. Теперь давайте узнаем как собирать компоненты в одно целое. + +## Главная цель: разделение ответственностей + +Создавая новые модульные компоненты, используя уже готовые компоненты с хорошо продуманными интерфейсами, вы получаете столько же преимуществ, сколько получили бы при использовании обычных функций и классов. Создание новых компонентов приводит к тому что вы объединяете их по ответственностям, где каждый компонент относится к своему типу задач. Создавая в приложении собственную библиотеку компонентов, вы будете создавать свои интерфейсы тем способом, который лучше всего вам подходит. + +## Пример составного компонента + +Давайте создадим компонент Avatar, который будет выводить фото и имя пользователя со страницы в Facebook. Для этого воспользуемся Facebook Graph API. + +```javascript +var Avatar = React.createClass({ + render: function() { + return ( +
+ + +
+ ); + } +}); + +var PagePic = React.createClass({ + render: function() { + return ( + + ); + } +}); + +var PageLink = React.createClass({ + render: function() { + return ( + + {this.props.pagename} + + ); + } +}); + +ReactDOM.render( + , + document.getElementById('example') +); +``` + +## Принадлежность компонентов + +В этом примере экземпляру `Avatar` *принадлежат* экземпляры `PagePic` и `PageLink`. В React **владельцем считается тот компонент, который устанавливает значения `props` другим компонентам**. Другими словами, если компонент `X` создается в методе `render()` компонента `Y`, то говорят, что `X` *принадлежит* `Y`. Компонент не может менять значения своих `props`, — они всегда содержат те значения, которые установил ему компонент-владелец. Следование этому правилу позволит избежать ошибок при работе с интерфейсом. + +В отношениях владелец-подчиненный и родитель-потомок есть важное различие. Отношение владелец-подчиненный возможно только в React, а отношение родитель-потомок вам известно из структуры DOM-дерева. В нашем примере `Avatar` будет владельцем экземпляров `div`, `PagePic` и `PageLink`, а `div`, в свою очередь, будет **родителем** (но не владельцем) элементов `PagePic` и `PageLink`. + +## Потомки + +Когда вы создаете экземпляр компонента React, вы можете дополнять его другими React-компонентами или выражениями на JavaScript внутри открывающего и закрывающего тегов вот так: + +```javascript + +``` + +`Родитель` может обращаться к своим потомкам через свойство `this.props.children`. **`this.props.children` это специальная структура данных:** используйте [вспомогательные методы React.Children](/react/docs/top-level-api.html#react.children), чтобы работать с ней. + +### Согласование потомков + +**Согласование - процесс, с помощью которого React обновляет DOM во время отрисовки интерфейса.** React проводит согласование потомков компонента в той последовательности, в которой они были отрисованы ранее. Предположим, при повторной отрисовке был сгенерирован следующий код: + +```html +// Отрисовка № 1 + +

Paragraph 1

+

Paragraph 2

+
+// Отрисовка № 2 + +

Paragraph 2

+
+``` + +Можно предположить, что будет удален узел `

Paragraph 1

`. Однако, React выстроит DOM по-своему; он изменит текст у первого потомка, а второго потомка удалит. React проводит согласование в соответствии с *расположением* дочерних узлов. + +### Потомки с состоянием + +Для большинства компонентов такой проблемы нет. Однако, у тех компонентов, которые хранят данные в `this.state` при повторной отрисовке могут возникнуть проблемы. + +Чтобы их избежать, дочерние элементы, вместо того чтобы удалить, иногда прячут: + +```html +// Отрисовка № 1 + +

Paragraph 1

+

Paragraph 2

+
+// Отрисовка № 2 + +

Paragraph 1

+

Paragraph 2

+
+``` + +### Динамичные потомки + +Ситуация осложняется, когда потомки перемешиваются между собой (например, при выдаче результатов поиска) или если новые компоненты добавляются в начало списка (как происходит в потоках). Если после каждой отрисовки потомок должен сохранять своё состояние и местоположение, вам надо присвоить ему уникальный идентификатор с помощью атрибута `key`: + +```javascript + render: function() { + var results = this.props.results; + return ( +
    + {results.map(function(result) { + return
  1. {result.text}
  2. ; + })} +
+ ); + } +``` + +Когда React будет проводить согласование потомков с такими ключами, они гарантированно обработаются корректно. + +Этот уникальный ключ должен *всегда* указываться как атрибут компонента, но не как свойство HTML-тега: + +```javascript +// Неверно! +var ListItemWrapper = React.createClass({ + render: function() { + return
  • {this.props.data.text}
  • ; + } +}); +var MyComponent = React.createClass({ + render: function() { + return ( + + ); + } +}); +``` +```javascript +// А так правильно :) +var ListItemWrapper = React.createClass({ + render: function() { + return
  • {this.props.data.text}
  • ; + } +}); +var MyComponent = React.createClass({ + render: function() { + return ( + + ); + } +}); +``` + +Также вы можете добавить идентификаторы потомкам используя объект ReactFragment. Подробнее смотрите [Фрагменты с ключами](create-fragment.html). + +## Передача данных + +В React передача данных от компонета-владельца к подчиненным компонентам происходит через `props`. Это довольно эффективный способ передачи данных: компоненты-владельцы могут устанавливать значения `props` компонентам которые ему принадлежат, используя свои `props` или `state`. + +## Замечание о производительности + +Вы можете подумать, что изменение данных будет слишком дорогостоящей операцией, если подчиненных узлов будет много. Хорошо что JavaScript работает достаточно быстро и методы `render()` обычно просты, так что приложения будут выполняться также быстро. Чаще всего самым узким местом в программе будут операции по изменению DOM, а не работа JS. Отслеживая происходящие в DOM изменения, React заметно сокращает время на выполнение этих операций. + +Однако, вам может понадобиться полный контроль над происходящим. В этом случае, переопределите метод `shouldComponentUpdate()` так, чтобы он возвращал false, этим вы полностью отключите обработку поддеревьев React. Более подробно об этом читайте в [справочнике React](/react/docs/component-specs.html). + +> Замечание: +> +> Если метод `shouldComponentUpdate()` вернет false в тот момент, когда данные только что изменились, React не станет обновлять интерфейс. Вы должны четко понимать что делаете, чтобы пользоваться этим приемом. Используйте его только когда заметите проблему производительности. Всё-таки, JavaScript работает гораздо быстрее чем, происходят изменения в DOM.