Livewire 执行双重查询

Livewire performing double queries

我正在检查 laravel-调试栏,发现查询量是应该的两倍(在我看来)

Laravel 调试栏:

虽然在渲染视图时应该只调用一次,

Livewire Class :

class AllTodos extends Component
{
    use WithPagination;

    public $todoId;

    protected $listeners = [
        'todoAdded' => '$refresh',
        'deleteConfirmed' => 'delete',
        'completeConfirmed' => 'complete'
    ];

    public function deleteConfirmation($id)
    {
        $this->todoId = $id;
        $this->dispatchBrowserEvent('alertConfirmation', [
            'message' => 'Are you sure want to delete this task ?',
            'action' => 'deleteConfirmed'
        ]);
    }

    public function delete()
    {
        $todo = Todo::findOrFail($this->todoId);
        $todo->delete();

        $this->dispatchBrowserEvent('alertInfo', [
            'message' => 'Todo has been deleted.',
            'icon' => 'success'
        ]);
    }

    public function completeConfirmation($id)
    {
        $this->todoId = $id;

        $this->dispatchBrowserEvent('alertConfirmation', [
            'message' => 'Are you sure want to complete this task ?',
            'action' => 'completeConfirmed'
        ]);
    }

    public function complete()
    {
        $todo = Todo::findOrFail($this->todoId);
        $todo->update([
            'is_completed' => 1
        ]);

        $this->dispatchBrowserEvent('alertInfo', [
            'message' => 'Todo has been completed.',
            'icon' => 'success'
        ]);
    }

    public function render()
    {
        return view('livewire.all-todos', [
            'todos' => Todo::latest()->paginate(5)
        ]);
    }
}

观点:

<div>
    <livewire:add-todo />
    <table class="w-full m-4">
        <thead class="text-md font-semibold tracking-wide text-left text-gray-900 bg-gray-100 uppercase border-b border-gray-600">
            <th class="px-4 py-3">Title</th>
            <th class="px-4 py-3">Action</th>
        </thead>
        <tbody class="bg-white">
            @foreach($todos as $todo)
                <tr class="text-gray-700">
                    <td class="px-4 py-3 border">{{ $todo->title }}</td>
                    <td class="px-4 py-3 border">
                        <button class="p-2 pl-5 pr-5 transition-colors duration-700 transform bg-indigo-500 hover:bg-blue-400 text-gray-100 text-lg rounded-lg focus:border-4 border-indigo-300" wire:click.prevent="completeConfirmation({{ $todo->id }})">Complete</button>
                        <button class="p-2 pl-5 pr-5 transition-colors duration-700 transform bg-red-500 hover:bg-red-400 text-gray-100 text-lg rounded-lg focus:border-4 border-red-300" wire:click="deleteConfirmation({{ $todo->id }})">Delete</button>
                    </td>
                </tr>
            @endforeach    
        </tbody>
    </table>
    <div class="m-4">
        {{ $todos->links() }}
    </div>
</div>

更新

布局:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <link href="{{ asset('css/app.css') }}" rel="stylesheet" type="text/css" />

    @livewireStyles
    <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.8.2/dist/alpine.min.js" defer></script>
</head>
<body>
    <section class="container mx-auto p-6 font-mono">
        <div class="w-full mb-8 overflow-hidden rounded-lg shadow-lg">
            <div class="w-full overflow-x-auto">
                <livewire:all-todos />
            </div>
        </div>            
    </section>

    <x-alerts />

    <script src="{{ asset('js/swal.js') }}"></script>
    
    @stack('js')

    @livewireScripts
</body>
</html>

我尝试使用 mount 特殊方法,结果是同样的双重查询, 如何减少这些查询量?

正如我们在评论中发现的那样,这里的问题是您的布局中没有 slot - 这是注入整页 Livewire 组件的地方。相反,您使用 <livewire:all-todos />.

直接在布局中呈现组件

这意味着两件事,

  1. 您的组件被调用了两次(但只渲染了一次,因为整页组件没有插槽,但内联渲染按预期工作)
  2. 您的 all-todos 组件将在使用该布局的 所有 页面上呈现。

这里的第一点是您收到双重查询的原因。

解决方案

要解决您的问题,您只需将 <livewire:all-todos /> 组件的内联渲染替换为魔术变量 {{ $slot }}.

<section class="container mx-auto p-6 font-mono">
    <div class="w-full mb-8 overflow-hidden rounded-lg shadow-lg">
        <div class="w-full overflow-x-auto">
            {{ $slot }}
        </div>
    </div>            
</section>

相关阅读material,