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

Я собрал простое приложение ToDo, состояние которого поддерживается только в верхнем компоненте контейнера.

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

Мы создадим приложение ToDo, в котором вы сможете добавлять элементы, отмечать их как завершенные и отменять.

Мы собираемся построить следующие компоненты.

  1. todoAction.evt - событие приложения, которое запускается дочерними компонентами для изменения состояния. (Соглашение об именах: верблюжья оболочка для мероприятий)
  2. ToDoApp.app - приложение верхнего уровня, действует как контейнер и, что наиболее важно, поддерживает состояние приложения. Обрабатывает событие todoAction.
  3. ToDoList.cmp - компонент без сохранения состояния для перебора списка Todo и рендеринга компонента ToDoItem
  4. ToDoItem.cmp - компонент без сохранения состояния для отображения каждого элемента Todo и запускает событие приложения с полезной нагрузкой для изменения состояния
  5. ToDoItemNew.cpm - компонент без сохранения состояния для добавления нового элемента Todo и запускает событие приложения с полезной нагрузкой для изменения состояния

Это все, что нужно.

Давайте теперь погрузимся в код.

1. todoAction.evt

<aura:event type="APPLICATION" description="todoAction">
    <aura:attribute type="String" name="type"/>
    <aura:attribute type="Object" name="payload"/>
</aura:event>

Это событие приложения принимает 2 параметра,

type: это будет тип выполняемого действия, «Пример TOGGLE_COMPLETE», который будет передан дочерними компонентами, когда он хочет обновить состояние.

полезная нагрузка: фактическая полезная нагрузка, «Пример {Id: 1}». дочерний компонент также передаст эти параметры

2. ToDoApp.app

Приложение-контейнер верхнего уровня и единственный компонент, который будет поддерживать состояние во всем этом приложении.

Этот компонент будет содержать дочерний компонент для отображения списка задач, но, что наиболее важно, помощник будет иметь действия для изменения состояния. Текущее состояние хранится в v.state, и это один большой объект, содержащий все состояние приложения.

Код ToDoApp.app:

<!--
 ToDoApp.app
 -->

<aura:application description="ToDoApp" extends="force:slds" access="global" extensible="true">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:handler event="c:todoAction" action="{!c.handleAction}"/>

    <aura:attribute type="Object" name="state"/>
   <div class="slds-page-header">
        <div class="slds-media">
            <div class="slds-media__body">
               <h1 class="slds-page-header__title slds-truncate slds-align-middle slds-text-align_center" title="ToDo">ToDo App</h1>
            </div>
        </div>
    </div>
    <c:ToDoList state="{!v.state}" />
</aura:application>

Код помощника:

/**
 * ToDoAppHelper.js
 */
({
    getNextState: function(prevState, action){
        var nextState = prevState;

        switch(action.type){
            case 'GET_DEFAULT_STATE':
                // Make an apex call to fetch initial data
                var defaultStore =
                    [
                        {Id: 1, Item: "Complete ToDo sample", IsCompleted: true},
                        {Id: 2, Item: "Post in medium", IsCompleted: false}
                    ]
                nextState = defaultStore;
                break;
            case 'TOGGLE_COMPLETE':
                nextState.map((todo, index) => {
                    if(todo.Id == action.payload.Id){
                        todo.IsCompleted = !todo.IsCompleted;
                    }
                });
                break;
            case 'ADD_NEW_TODO':
                const maxId = Math.max.apply(Math,nextState.map(function(item){return item.Id;}))
                nextState.push({Id: maxId + 1, Item: action.payload.NewToDo, IsCompleted: false});
            default:
                break;
        }
        return nextState;
    }
})

3. ToDoItem.cmp:

Это снова компонент без состояния для отображения каждого элемента ToDo вместе с кнопкой состояния этого элемента «Готово или Не выполнено». Нажатие кнопки должно переключать состояние завершения, это происходит путем запуска события приложения с полезной нагрузкой (идентификатором элемента) и действием TOGGLE_COMPLETE, которое будет обрабатываться в ToDoApp.app верхнего уровня.

/**
 * ToDoItemController.js
 */
({
    toggleComplete: function(component, event){
        const todoId = component.get('v.todo.Id');
        const dispatch = $A.get('e.c:todoAction');
        dispatch.setParam('type', 'TOGGLE_COMPLETE');
        dispatch.setParam('payload', {Id: todoId});
        dispatch.fire();
    }
})

Я надеюсь, что это дает общее представление об одном из различных способов разработки компонентов для поддержания состояния из одного места.

Короче,

ToDoApp - обрабатывает событие приложения, обрабатывает состояние и размещает дочерний компонент

Дочерние компоненты - запускают событие приложения с полезной нагрузкой и действием и не имеют состояния

Вы можете получить всю базу кода здесь по моей ссылке на GitHub.

На основе архитектуры Redux и сеанса Джейд Пенниг / Адама Путински в Dreamforce’17.