Как запустить метод JavaScript после обновления и повторной визуализации компонента Livewire?

Я хочу запустить метод javascript под названием makeFinalAdjustments(), но это должно произойти после того, как страница завершит повторную отрисовку содержимого после события щелчка внутри этого компонента livewire:

//CHILD LIVEWIRE COMPONENT

//Child.blade.php
<div>
     <div wire:click = "updateContent($id)">Click here</div>
     <div>{{ $content }}</div>
     ....
</div>

//Child.php
public $content;
public $id;
public function updateContent()
{
    $this->dispatch('updateContent');
}


//PARENT LIVEWIRE COMPONENT

//Parent.php
protected $listeners = [
    'updateContent' => 'handleUpdateContent',
];

public function handleUpdateContent($child_id): void
{
    $this->content[$child_id] = $this->getSomeContent($child_id);
}

//parent.blade.php
<div>
    @foreach(child in list)
        <livewire:child :content=content[child->id]>
    @endforeach
    ...
</div>

Я попробовал добавить прослушиватель событий на основе документации здесь....

document.addEventListener('livewire:init', function () {
        Livewire.on('updateContent', () => {
            Livewire.hook('commit', ({ component, commit, respond, succeed, fail }) => { 
                succeed(({ snapshot, effect }) => {
                    queueMicrotask(() => {
                        makeFinalAdjustments();
                    })
                })
            })
        });
    });

...но это не работает, потому что makeFinalAdjustments() срабатывает слишком рано, до того, как новый контент завершит рендеринг.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема не совсем ясна, надо понять, что выполняется в функции makeFinalAdjustments().

В любом случае я попытался сымитировать ситуацию, реконструируя неполные части запроса.

Родительский класс

class ParentTest extends Component
{
    public array $content = [];
    public array $children = [];

    protected $listeners = [
        'updateContent' => 'handleUpdateContent',
    ];


    public function mount() {

        $this->children = [

            (object)['id' => 1],
            (object)['id' => 2],
            (object)['id' => 3],
        ];

        $this->content = [

            1 => Str::random(),
            2 => Str::random(),
            3 => Str::random()
        ];
    }


    public function handleUpdateContent($child_id): void
    {
        // for this test we use a value of convenience

        // $this->content[$child_id] = $this->getSomeContent($child_id);
        $this->content[$child_id] = Str::random();
    }
}

Родительский вид

<div>

    @foreach($children as $child)

        <livewire:child-test :content = "$content[$child->id]"
                             :id = "$child->id" 
                             :key = "$child->id"
        >

        <br>
        <hr>
        <br>

    @endforeach

</div>

Дочерний класс

namespace App\Livewire;

use Livewire\Attributes\Reactive;
use Livewire\Component;

class ChildTest extends Component
{
    public $id;

    #[Reactive]
    public $content;


// --- since the event is now dispatched from the frontend this is no longer needed
//
//    public function updateContent($id)
//    {
//        $this->dispatch('updateContent', child_id: $id);
//    }
}

Детский вид

<div>

    {{--<div wire:click = "updateContent({{ $id }})">--}}
    <div wire:click = "$dispatch('updateContent', {child_id: {{ $id }} })">  {{--  <~~~ now the event is dispatched from the frontend --}}
        [Click here]
    </div>

    <div x-init = "$watch('$wire.content', () => $nextTick(() => makeFinalAdjustments({{ $id }})))">

        <span id = "content-{{ $id }}">
            {{ $content }}
        </span>

        <span id = "revContent-{{ $id }}">
        </span>

    </div>

</div>


<script>

    function makeFinalAdjustments(id)
    {
        const content = document.getElementById(`content-${id}`).textContent;

        const revContent = content.split("").reverse().join("");
        document.getElementById(`revContent-${id}`).textContent = revContent;
    }
</script>
  • В родительском классе я эмулировал исходное содержимое общедоступных переменных, используя для содержимого несколько случайных строк.

  • В обработчике событий handleUpdateContent() я заменил getSomeContent() новой случайной строкой.

  • В родительском представлении я указал содержимое и параметры идентификатора, а также добавил уникальный ключ

  • Свойство $content дочернего класса имеет атрибут #[Reactive], поэтому изменение родительского класса отражается на связанном дочернем классе.

  • Я отправил событие дочернего компонента из представления, поэтому сохранил вызов бэкэнда, и дочерний метод updateContent() больше не нужен.

  • В дочернем представлении я добавил $watch для переменной $wire.content с помощью Alpine, поэтому при ее изменении в $nextTick вызывается функция makeFinalAdjustments().

  • функция makeFinalAdjustments() в этом тесте считывает содержимое из DOM и обновляет элемент revContent, используя обратную версию оригинала: как вы можете видеть, с помощью $nextTick функция makeFinalAdjustments() вызывается, когда обновление компонента завершается. сторона Livewire. Вы увидите, что Livewire восстанавливает все содержимое revContent как пустое, но затем содержимое revContent, связанное с нажатой кнопкой, заполняется.

Решением было добавление уникального ключа. Спасибо.

Urbycoz 15.07.2024 17:31

Другие вопросы по теме