【问题标题】:Why does Livewire run a new query on each render and why are relationships lost为什么 Livewire 会在每次渲染时运行一个新查询以及为什么会丢失关系
【发布时间】:2021-05-26 05:24:40
【问题描述】:

场景

我想做什么

我正在创建一个多列用户索引页面,其中右列显示左列中选择的用户的详细信息。 选中后,用户不会被拉出集合,而是刚从数据库中拉出,因此数据是最新的。

我使用 livewire 文档中描述的方法延迟加载用户列表。

用户具有“角色”关系,显示在列表列中。

我的期望

我希望一旦将 $this→users 设置为用户的集合并选择了一个用户,只有查询才会触发以获取该用户的数据。

实际发生的情况

当一个用户被选中时,从数据库中获取所有用户的查询(再次)运行,并且由于来自用户的角色显示在列表视图中,对于每个用户,一个新的查询是执行。 之后,执行获取所选用户的查询。然后触发另一个获取用户角色的查询。

所以我的问题

  1. 为什么 Livewire 会丢失在公共 $users 的第一个声明中急切加载的关系?
  2. 为什么 Livewire 重新运行查询以获取所有用户,而公共 $users 已经定义为用户集合?

文件:

  • UserListDetail.php
    <?php

    namespace App\Http\Livewire;

    use App\Models\User;
    use Livewire\Component;

    class UsersListDetail extends Component {

        public string $search   = '';
        public        $users;
        public        $selectedUser;
        public int    $timesRun = 0;

        public bool $readyToLoadUserList = false;

        protected $queryString = [
            'search' => [ 'except' => '' ],
        ];

        // Defer loading users
        public function readyToLoadUserList()
        {
            // Get all users with roles relationship
            $this->users = User::with('roles')->get();

            $this->readyToLoadUserList = true;
        }

        public function selectUser(int $userId)
        {
            $this->selectedUser = User::with('roles')->find($userId);
        }

        public function render()
        {
            return view('livewire.users-list-detail', [
                    'selectedUser' => $this->selectedUser,
                ]
            );
        }
    }
  • user-list-detail.blade.php 的简化版
<div>
    <div wire:init="readyToLoadUserList">
        @if($readyToLoadUserList)
            <ul>
                @foreach($users as $user)
                    <li wire:click="selectUser({{ $user->id }})">
                        {{ $user→name_first }} {{ $user→name_last }},
                        @foreach($user→roles as $role)
                            {{ $role→label }},
                        @endforeach
                    </li>
                @endforeach
            </ul>
        @endif
    </div>

    <div>
        @isset($selectedUser)
            {{ $name_first
        @endisset
    </div>
</div>

【问题讨论】:

  • 你找到什么了吗?
  • 你找到解决办法了吗?

标签: php laravel laravel-livewire


【解决方案1】:

selectUser() 方法被触发时,livewire 将重新渲染刀片,并且由于存在wire:init="readyToLoadUserList",它会(再次)加载每个用户。

readyToLoadUserList() 替换为mount() 并保持wire:init="" 为空。

另外,@if($users-&gt;count() &gt; 0) 条件

【讨论】:

  • init 只会加载一次。当我在函数 readyToLoadUserList ($this→foo+++) 中添加一个计数器时;它只增加一次。所以我不认为这是问题所在。
猜你喜欢
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 2022-01-20
  • 2017-11-22
相关资源
最近更新 更多