Livewire 组件更新并重新渲染后如何运行 JavaScript 方法?

问题描述 投票:0回答:1

我想运行一个名为

makeFinalAdjustments()
的 JavaScript 方法,但它需要在页面完成重新渲染此 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>

我尝试根据文档添加事件监听器here....

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

...但它不起作用,因为

makeFinalAdjustments()
在新内容完成渲染之前触发得太早。

javascript laravel-livewire event-listener laravel-11 livewire-3
1个回答
0
投票

问题还没有完全弄清楚,我们应该明白 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
    {
        // $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>
  • 在父类中,我使用一些随机字符串来模拟公共变量的初始内容content

  • handleUpdateContent() 事件处理程序中,我将 getSomeContent() 替换为新的随机字符串

  • 在父视图中,我提供了 contentid 参数,我还添加了一个 unique key

  • 子类的$content属性具有属性#[Reactive],因此父类中的更改会反映到相关子类

  • 我从视图中调度了子组件事件,因此我保存了对后端的调用,并且不再需要子组件的 updateContent() 方法

  • 在子视图中,我使用 Alpine 在 $wire.content 变量上添加了 $watch,因此当它发生更改时,会在 $nextTick 处调用 makeFinalAdjustments() 函数。

  • 此测试中的 makeFinalAdjustments() 从 DOM 读取 content 并更新 revContent 元素:如您所见,使用 $nextTick makeFinalAdjustments() 在更新组件在Livewire端完成。 您将看到 Livewire 将所有 revContent 内容恢复为空,但随后与单击的按钮相关的 revContent 被填充

© www.soinside.com 2019 - 2024. All rights reserved.