Обращение к родительскому компоненту

В Slim.js компоненты строятся на принципах веб-компонентов, но с упрощённой системой связывания данных и реактивностью. Один из ключевых аспектов — взаимодействие между компонентами, в частности возможность обращения к родительскому компоненту из дочернего. Это необходимо для управления состоянием, передачи событий или вызова методов родителя.


Контекст родительского компонента

Каждый компонент в Slim.js имеет свой жизненный цикл и область видимости. Дочерний компонент, находясь внутри родителя, может получить доступ к нему через ссылку на DOM или через механизм this.parent, если компонент создан с поддержкой иерархии Slim.js.

Прямой доступ к родителю реализуется так:

class ChildComponent extends Slim {
    get parentComponent() {
        return this.parent; // Ссылка на родительский компонент Slim.js
    }

    callParentMethod() {
        if(this.parentComponent && typeof this.parentComponent.parentMethod === 'function') {
            this.parentComponent.parentMethod('данные из дочернего');
        }
    }
}

ChildComponent.useShadow = false;
customElements.define('child-component', ChildComponent);

Ключевые моменты:

  • this.parent указывает на ближайший родительский компонент Slim.js в DOM.
  • Метод родителя должен быть публичным и доступным для вызова.
  • Если родитель отсутствует, this.parent будет null, что следует проверять.

Передача событий через CustomEvent

Другой подход — использование событий. Дочерний компонент создаёт событие, которое всплывает к родителю:

class ChildComponent extends Slim {
    notifyParent() {
        this.dispatchEvent(new CustomEvent('childAction', {
            bubbles: true,
            composed: true,
            detail: { message: 'Данные от дочернего' }
        }));
    }
}

ChildComponent.useShadow = false;
customElements.define('child-component', ChildComponent);

Родительский компонент подписывается на событие:

class ParentComponent extends Slim {
    constructor() {
        super();
        this.handleChildAction = this.handleChildAction.bind(this);
    }

    handleChildAction(event) {
        console.log('Получено от дочернего:', event.detail.message);
    }

    template() {
        return `
            <child-component onchildAct ion="handleChildAction"></child-component>
        `;
    }
}

ParentComponent.useShadow = false;
customElements.define('parent-component', ParentComponent);

Преимущества этого подхода:

  • Слабое связывание компонентов.
  • Возможность передачи данных через event.detail.
  • Совместимость с Shadow DOM благодаря composed: true.

Вызов методов родителя через слоты

Slim.js поддерживает слоты, что позволяет дочерним компонентам работать с DOM, переданным родителем:

class ParentComponent extends Slim {
    parentMethod(data) {
        console.log('Метод родителя вызван с данными:', data);
    }

    template() {
        return `
            <slot name="child-slot"></slot>
        `;
    }
}

class ChildComponent extends Slim {
    connectedCallback() {
        super.connectedCallback();
        const parent = this.closest('parent-component');
        if(parent) {
            parent.parentMethod('данные через слот');
        }
    }
}

Использование слотов даёт доступ к DOM родителя, но требует аккуратности, чтобы избежать циклических вызовов и конфликтов с Shadow DOM.


Рекомендации по архитектуре

  • Для простого обмена данными лучше использовать события (CustomEvent), так сохраняется слабое связывание.
  • Прямой вызов методов родителя оправдан только при тесной логической связи компонентов.
  • Всегда проверять наличие родителя через this.parent или closest(), чтобы избежать ошибок во время рендеринга.
  • Разделять методы и свойства, предназначенные для дочерних компонентов, и внутренние методы родителя, чтобы предотвратить случайное вмешательство.

Примеры практических сценариев

  1. Форма и контроллер: дочерний компонент ввода данных вызывает метод родителя для валидации.
  2. Список и элементы: дочерний элемент списка уведомляет родителя о событии выбора.
  3. Модальные окна: кнопки внутри модального окна вызывают методы родителя для закрытия или подтверждения действия.

Использование этих подходов позволяет строить реактивные, легко расширяемые интерфейсы с поддержкой вложенных компонентов в Slim.js.