События в Aura Components

Часто при разработке Lightning Platform apps или Community используются Aura Component-ы. Для тех, кто не знаком с тем, что это такое и с чем его едят — вот ссылка для ознакомления: Trailhead module.

Мы же пойдем чуть-чуть дальше и рассмотрим вопрос взаимодействия между компонентами или, другими словами, передачу данных из одного компонента в другой.

Как Вы помните, основой построения Lightning Platform apps является возможность композиции или вложения одного Aura Component в другой. При этом, естественно, возникает необходимость передачи данных между компонентами. Есть несколько способов это сделать (например aura:attribute, aura:method), но сегодня мы рассмотрим как компоненты могут общаться между собой при помощи Event.

Event могут быть двух типов:

  • Component
  • Application

Разница между двумя типами событий в том, кто может “подписаться” на это событие. В случае Event типа Component это может быть только компонент, который находится выше по иерархии или сам компонент, который вызывает Event. Если же Event типа Application, то “подписаться” на это событие может любой компонент, вне зависимости от иерархии. Salesforce рекомендует использовать Event типа Component вместо Application, так как это позволяет лучше контролировать “подписчиков” события.

Cоздадим и используем Event типа Component. При помощи Event изменим значение атрибута в другом компоненте.

Логика работы

  1. Пользователь кликает кнопку в Children компоненте, который вложен в Parent компонент
  2. JS контроллер Children компонента устанавливает текст сообщения в Event
  3. Parent компонент, который подписан на Event, обрабатывает событие
  4. JS контроллер parent компонента устанавливает значение атрибута этого компонента на основе данных полученных в Event

Создадим Event

Для этого заходим в Developer Console
1

и создаем Event с именем ComponentEvent, который содержит один атрибут типа String

<aura:event type="COMPONENT">
    <aura:attribute name="message" type="String"/>
</aura:event>

Затем создаем компонент EventChildComponent

<aura:component >
    <aura:registerEvent name="cmpEvent" type="c:ComponentEvent"/>

    <h1>Simple Component Event Sample</h1>
    <p><lightning:button
        label="Click here to fire a component event"
        onclick="{!c.fireComponentEvent}" />
    </p>
</aura:component>

При помощи строки

<aura:registerEvent name="cmpEvent" type="c:ComponentEvent"/>

мы регистрируем в этом компоненте Event типа ComponentEvent, который мы создали ранее.

В компонент также добавлена кнопка, нажатие на которую обрабатывается методом fireComponentEvent из JS контроллера компонента.

Создадим этот метод

({
        fireComponentEvent : function(cmp, event) {
        var cmpEvent = cmp.getEvent("cmpEvent");
        cmpEvent.setParams({
            "message" : "A component event fired me. " +
            "It all happened so fast. Now, I'm here!" });
        cmpEvent.fire();
    }
})

В этом методе сначала мы получаем Event компонента по атрибуту name, который мы указали при регистрации Event
Регистрация

<aura:registerEvent name="cmpEvent" type="c:ComponentEvent"/>

Получение

var cmpEvent = cmp.getEvent("cmpEvent");

Устанавливаем значение атрибута Event-а с name=“message”

cmpEvent.setParams({
"message" : "A component event fired me. " +
"It all happened so fast. Now, I'm here!" });

Запускаем событие

cmpEvent.fire();

Теперь создадим компонент EventParentComponent

<aura:component >
    <aura:attribute name="messageFromEvent" type="String"/>
    <aura:attribute name="numEvents" type="Integer" default="0"/>

    <aura:handler name="cmpEvent" event="c:ComponentEvent" action="{!c.handleComponentEvent}"/>

    <c:EventChildComponent />
    
    <p>{!v.messageFromEvent}</p>
    <p>Number of events: {!v.numEvents}</p>
</aura:component>

Как видите, этот компонент содержит в себе компонент

<c:EventChildComponent />

и обработчик события

<aura:handler name="cmpEvent" event="c:ComponentEvent" action="{!c.handleComponentEvent}"/>

При этом атрибут name=“cmpEvent” совпадает с атрибутом name, который мы указывали при регистрации события в компоненте EventChildComponent

<aura:registerEvent name="cmpEvent" type="c:ComponentEvent"/>

Обработка Event осуществляется методом handleComponentEvent из JS контроллера компонента EventParentComponent

({
        handleComponentEvent : function(cmp, event) {
        var message = event.getParam("message");
        cmp.set("v.messageFromEvent", message);
        var numEventsHandled = parseInt(cmp.get("v.numEvents")) + 1;
        cmp.set("v.numEvents", numEventsHandled);
    }
})

При помощи

var message = event.getParam("message");

мы получаем значение, переданное в атрибуте message Event-a, и устанавливаем его в качестве значения атрибута компонента messageFromEvent.

Осталось вставить EventParentComponent в aura:application и можно тестировать.

<aura:application >
  <c:EventParentComponent/>
</aura:application>

Теперь создадим и используем Event типа Application.

Логика работы очень похожа на ту, которая использовалась в примере с Event типа Component. Единственное отличие: здесь не будет Parent и Child компонентов.

  1. Пользователь кликает кнопку в EventComponent
  2. JS контроллер EventComponent устанавливает текст сообщения в Event
  3. HandlerComponent, который подписан на Event, обрабатывает событие
  4. JS контроллер HandlerComponent устанавливает значение атрибута этого компонента на основе данных полученных в Event

Создадим Event
Для этого заходим в Developer Console и создаем Event с именем ApplicationEvent, который содержит один атрибут типа String

<aura:event type="APPLICATION">
    <aura:attribute name="message" type="String"/>
</aura:event>

Далее создаем компонент с именем EventComponent с зарегистрированным Event

<aura:component >
    <aura:registerEvent name="appEvent" type="c:ApplicationEvent"/>

    <h1>Simple Application Event Sample</h1>
    <p><lightning:button
        label="Click here to fire an application event"
        onclick="{!c.fireApplicationEvent}" />
    </p>
</aura:component>

При помощи строки

<aura:registerEvent name="appEvent" type="c:ApplicationEvent"/>

мы регистрируем в этом компоненте Event типа ApplicationEvent, который мы создали ранее.

В компонент также добавлена кнопка, нажатие на которую обрабатывается методом fireApplicationEvent из JS контроллера компонента.

Создадим этот метод

({
        fireApplicationEvent : function(cmp, event) {
        var appEvent = $A.get("e.c:ApplicationEvent");
        appEvent.setParams({
        "message" : "An application event fired me. " +
        "It all happened so fast. Now, I'm everywhere!" });
        appEvent.fire();
      }
})

В этом методе сначала мы получаем Event, используя синтаксис

e.<namespace>.<event>
var appEvent = $A.get("e.c:ApplicationEvent");

Сравните с тем, какой синтаксис использовался при получении Event типа Component

var cmpEvent = cmp.getEvent("cmpEvent");

Устанавливаем значение атрибута Event-а с name=“message”

appEvent.setParams({
"message" : "An application event fired me. " +
"It all happened so fast. Now, I'm everywhere!" });

Запускаем событие

appEvent.fire();

Теперь создадим компонент HandlerComponent

<aura:component >
    <aura:attribute name="messageFromEvent" type="String"/>
    <aura:attribute name="numEvents" type="Integer" default="0"/>

    <aura:handler event="c:ApplicationEvent" action="{!c.handleApplicationEvent}"/>

    <p>{!v.messageFromEvent}</p>
    <p>Number of events: {!v.numEvents}</p>
</aura:component>

Как видите, этот компонент не содержит в себе компонент EventComponent, а содержит обработчик события

<aura:handler event="c:ApplicationEvent" action="{!c.handleApplicationEvent}"/>

Опять же, сравните, как объявлялся обработчик при использовании Event типа Component

<aura:handler name="cmpEvent" event="c:ComponentEvent" action="{!c.handleComponentEvent}"/>

Обработка Event осуществляется методом handleApplicationEvent из JS контроллера компонента HandlerComponent

({
       handleApplicationEvent : function(cmp, event) {
        var message = event.getParam("message");
        cmp.set("v.messageFromEvent", message);
        var numEventsHandled = parseInt(cmp.get("v.numEvents")) + 1;
        cmp.set("v.numEvents", numEventsHandled);
    }
})

Осталось вставить оба компонента в aura:application и можно тестировать.

<aura:application >
    <c:EventComponent/>
    <c:HandlerComponent/>
</aura:application>

Таким образом, мы можем передавать данные между различными компонентами.

7 Вподобань

У нас компания полностью уходит сейчас от разработки с aura components. Мы переходим на lightning web components. Новые компоненты пишутся на LWC и иногда переписываем по возможности старые aura компоненты. LWC может не всё еще могут, как аура, но они менее бажные, чем aura компоненты.

Только баги заставили переписывать вс на LWC?
Или есть ещё какие-то моменты?
Поправьте если я не так понял, но LWC компонент вы не сможете на орге поправить. Так?

да, баги и потому, что иногда теряется контекст самого компонента, особенно если работаешь с PopUp Window. Плюс плохая документация. На счет того, можно ли lwc поправить на орге, я не знаю. Я работаю через IntellijIdea.

Да на самом деле LWC сейчас не доступны для редактирования непосредственно на орге или в Dev Console