【问题标题】:Livewire performing double queriesLivewire 执行双重查询
【发布时间】:2021-12-04 15:16:01
【问题描述】:

我正在检查 laravel-debugbar,发现查询量是应有的两倍(在我看来)

Laravel 调试栏:

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

Livewire 类:

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 特殊方法,结果是同样的双重查询, 如何减少这些查询量?

【问题讨论】:

  • 这看起来不太正常,看起来像是在渲染两次。你如何渲染这个组件?
  • @Qirel 那在我的 AllTodos 类上,我使用 eloquent Todo::latest()->paginate(5) 在内置的 livewire render() 函数上渲染它,并将其传递给刀片视图,就是这样,这就是为什么我想知道出了什么问题
  • 不,我的意思是,你如何渲染整个组件?是整页组件,还是从另一个组件渲染出来的?
  • @Qirel 不,我用的是整页组件,直接传给路由 --> Route::get('/', AllTodos::class),渲染到app.layout,请查看我更新的问题
  • 但是你把它作为一个整页组件,那个渲染它,然后在布局中,你手动添加它添加好吗?所以它渲染了两次。但是由于您没有插槽,它只在视觉上呈现一次 - 但组件被调用两次,一次来自路由,一次来自&lt;livewire:all-todos /&gt;。如果您将该行替换为{{ $slot}},它应该可以工作并且只调用该组件一次

标签: laravel-8 laravel-livewire


【解决方案1】:

正如我们在 cmets 中发现的,这里的问题是您的布局中没有 slot - 这是注入整页 Livewire 组件的地方。相反,您可以使用 &lt;livewire:all-todos /&gt; 在布局中直接渲染组件。

这意味着两件事,

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

这里的第一点,就是你得到双重查询的原因。

解决办法

要解决您的问题,您只需将 &lt;livewire:all-todos /&gt; 组件的内联渲染替换为魔术变量 {{ $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>

相关阅读材料,

【讨论】:

    猜你喜欢
    • 2019-07-08
    • 2017-04-25
    • 2016-06-25
    • 2011-04-01
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多