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 />
.
直接在布局中呈现组件
这意味着两件事,
- 您的组件被调用了两次(但只渲染了一次,因为整页组件没有插槽,但内联渲染按预期工作)
- 您的
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,
我正在检查 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 />
.
这意味着两件事,
- 您的组件被调用了两次(但只渲染了一次,因为整页组件没有插槽,但内联渲染按预期工作)
- 您的
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>