Как обновить вложенные компоненты без обновления родительских

#laravel-livewire

Вопрос:

У меня есть таблица со строками моделей списков вакансий. В таблице можно отправить массовое действие в очередь. В моем родительском компоненте у меня есть массив $bulkIds и я добавляю массив каждого отправленного массового действия. Когда задание очереди завершено, я проверяю, совпадают ли идентификаторы для этого задания с сохраненными, и emit событие ( bulkActionCompleted ), если они совпадают. Это я получаю на вложенных компонентах. Я хочу обновить строки только в этом массиве, но без обновления родительского компонента. Пользователь может отправлять другие задания в очереди или просматривать страницы с другими результатами и т. Д. Я не хочу вмешиваться в работу пользователя.

Я пробовал работать с skipRender ними , но вы не можете пропустить визуализацию ребенка, и как только ребенок обновляется, это делает родитель.

В родительском html:

 <div id="job-listings-table" class="table-body col-12 p-0">
    @foreach($jobListings as $index => $jobListing)
        @php
            $isInBulk = in_array($jobListing->id, array_merge(...$bulkIds));
        @endphp

        <livewire:employer.job-listings.index.parts.row :jobListing="$jobListing"
                                                                    :isInBulk="$isInBulk"
                                                                    :lastJobIds="[]"
                                                                    :wire:key="$jobListing->id . now()">

       </livewire:employer.job-listings.index.parts.row>

                    
   @endforeach
</div>
 

Дочерний компонент:

 class Row extends Component
{
    public JobListing $jobListing;
    public bool $isInBulk;
    public array $lastJobIds = [];

    protected $listeners = [
        'bulkActionCompleted',
    ];

    public function render()
    {
        return view('livewire.employer.job-listings.index.parts.row');
    }

    public function bulkActionCompleted($jobListingIds)
    {
        $this->lastJobIds = $jobListingIds;
        if (in_array($this->jobListing->id, $jobListingIds)) {
            $this->isInBulk = false;
        }
    }
}
 

TL;DR: Я хочу обновить определенные вложенные компоненты без обновления родительского элемента.

Ответ №1:

Как оказалось, это поведение по умолчанию. Всякий раз, когда я запускаю событие, которое перехватывается дочерними компонентами, родительский элемент не обновляется «полностью», когда используется функция, которая запускает событие skipRender . Добавление wire:ignore статических элементов исправило проблему, возникшую при запуске функции в родительском компоненте.

Однако я не могу объяснить, почему части родительского элемента все еще обновлялись. Я думаю skipRender , что это не совсем пропускает визуализацию всего компонента.

Чтобы лучше объяснить, при skipRender вызове функция рендеринга даже не вызывается, но если у вас есть элементы, которые вы могли изменить с помощью JS (в моем примере раскрывающийся список, который отображается, когда установлен хотя бы один флажок), будет сброшен в исходное состояние. Кажется, что он не перерисовывает DOM, но он сбрасывается. Добавляя wire:ignore к этим конкретным элементам, проблема решается.