capevace/livewire-optimistic-ui

一个用于在 Laravel Livewire 中更好地支持乐观 UI 的实用程序包。

1.0.1 2024-06-09 17:54 UTC

This package is auto-updated.

Last update: 2024-09-09 18:33:50 UTC


README

Demo.mp4

安装

您可以通过 composer 安装此包

composer require capevace/livewire-optimistic-ui

示例

# In your Livewire component's .blade.php file
<x-optimistic::injector class="max-w-lg mx-auto mt-10">
  <x-demo.saving-indicator wire:loading.delay />

  <form
    class="w-full flex items-center gap-5 mb-10"
    x-data="{ text: '' }"
    @submit.prevent="
      $optimistic.addTask(text);
      text = '';
    "
  >
    <input
      autofocus
      name="text"
      x-model="text"
      placeholder="Type your task here..."
      class="flex-1 px-5 py-3 border shadow rounded-lg"
    />

    <button class="px-5 py-3 border shadow rounded-lg bg-green-400">Add +</button>
  </form>

  <x-demo.list>
    @foreach($todos as $task)
      <x-demo.task
        wire:key="{{ $task['id'] }}"
        x-optimistic
        x-optimistic.removed.remove
      >
        <x-demo.button @click="$optimistic.deleteTask('{{ $task['id'] }}')"/>

        <form
          x-data="{
            text: $item?.text ?? @js($task['text']),
          }"
          class="flex-1"
        >
          <x-demo.input
            name="text_{{ $task['id'] }}"
            x-model="text"
            x-optimistic.edited.class="italic"

            @input.debounce="$optimistic.editTask('{{ $task['id'] }}', text)"
          />
        </form>

      </x-demo.task>
    @endforeach

    <x-optimistic::added>
      <x-demo.task
        x-bind:data-id="$item.id"
        x-bind:wire:key="$item.id"
        x-optimistic.removed.remove
      >
        <x-demo.button @click="$optimistic.deleteTask($item.id)"/>

        <div class="flex-1">
          <x-demo.input
            x-bind:name="'text_' + $item.id"
            x-bind:value="$item.text"
            class="italic"
          />
        </div>
      </x-demo.task>
    </x-optimistic::added>
  </x-demo.list>
</x-optimistic::injector>
use Capevace\OptimisticUI\WithOptimisticUI;
use Capevace\OptimisticUI\Optimistic;

/**
 * @property-read Collection $todos
 */
class OptimisticPage extends Component
{
    use WithOptimisticUI;

    #[Optimistic(crud: 'create', model: Task::class, injectOptimisticId: true)]
    public function addTask(string $id, string $text): void
    {
        if (!uuid_is_valid($id) || Task::find($id)) {
            return;
        }

        $task = new Task([
            'text' => $text,
        ]);

        $task->id = $id;
        $task->save();
    }

    #[Optimistic(crud: 'delete', model: Task::class)]
    public function deleteTask(string $id): void
    {
        Task::find($id)?->delete();
    }

    #[Optimistic(crud: 'update', model: Task::class)]
    public function editTask(string $id, string $text): void
    {
        Task::find($id)?->update([
            'text' => $text,
        ]);
    }

    #[Computed]
    public function todos(): Collection
    {
        return Task::all();
    }

    public function render(): \Illuminate\View\View
    {
        return view("messages", [
            'todos' => $this->todos,
        ]);
    }
}

用法

将乐观 UI 添加到您的 Livewire 组件中

您需要使用 x-optimistic::injector 组件包裹您的 UI。此组件将为您处理乐观 UI。

<x-optimistic::injector class="max-w-lg mx-auto mt-10">
  <!-- Your UI here -->
</x-optimistic::injector>

然后,您可以通过使用 $optimistic 对象来乐观地调用您的函数。

<form
  @submit.prevent="
    $optimistic.addTask(text);
    text = '';
  "
>
    <input x-model="text" />
</form>

<!-- OR -->

@foreach($todos as $task)
  <form
    x-data="{ text: $item?.text ?? @js($task['text']) }"  
    @submit.prevent="$optimistic.editTask('{{ $task['id'] }}', text)"
  >
    <input x-model="text" />
  </form>
@endforeach

显示添加的项目

您可以使用 x-optimistic::added 指令来显示通过乐观方式添加的项目。组件将循环所有添加的项目,并将每个项目存储在 $item 变量中。

<x-optimistic::added>
  <x-demo.task
    x-bind:data-id="$item.id"
    x-bind:wire:key="$item.id"
  >
    <div x-text="$item.text"></div>
  </x-demo.task>
</x-optimistic::added>

乐观指令

您可以将 x-optimistic 指令添加到注入给定项目的乐观状态。ID 将从 wire:key 属性推断出来,或者可以通过 x-optimistic="<id>" 传递。

<x-demo.task 
    x-optimistic
    x-optimistic.edited.class="italic"
    x-optimistic.removed.remove
>
  <!-- Your task here -->
</x-demo.task>

乐观函数

要向您的 Livewire 组件添加乐观函数,您可以使用 #[Optimistic] 属性。

use Capevace\OptimisticUI\Optimistic;

#[Optimistic(
    fn: "update(params[0], { message: params[1] })"
)] 
public function changeMessage(string $id, string $message): void
{
    Message::find($id)->update([
        'message' => $message,
    ]);
}

fn 参数中的 JavaScript 将在函数被调用时在客户端执行。params 数组包含传递给函数的参数。

本地生成 ID

在创建新项目时,将为项目生成一个新的 UUID。此 ID 识别正在传输中的项目。如果您使用此 ID 实际创建项目,则可以支持与正在传输的项目交互,因为它们将被排队。

要使用此功能,请将 injectOptimisticId 参数设置为 true

本地,您仍然会调用 $optimized.addTask(text),但 ID 将在服务器端注入。

#[Optimistic(
    fn: "create({ text: params[0] })"
    injectOptimisticId: true
)]
public function addTask(string $id, string $text): void
{
    if (!uuid_is_valid($id) || Task::find($id)) {
        return;
    }

    $task = new Task([
        'text' => $text,
    ]);

    $task->id = $id;
    $task->save();
}

现成的 CRUD 函数

最常用的函数已通过 crud 参数实现。

将此设置为 createupdatedelete 将使用反射检查您的 PHP 函数参数,并自动为您生成 JavaScript 函数。

您还需要提供 model 参数,它将用于仅允许更新 fillable 属性。

#[Optimistic(crud: 'create', model: Task::class)]
public function addTask(string $id, string $text): void
{
    if (!uuid_is_valid($id) || Task::find($id)) {
        return;
    }

    $task = new Task([
        'text' => $text,
    ]);

    $task->id = $id;
    $task->save();
}

#[Optimistic(crud: 'delete', model: Task::class)]
public function deleteTask(string $id): void
{
    Task::find($id)?->delete();
}

#[Optimistic(crud: 'update', model: Task::class)]
public function editTask(string $id, string $text): void
{
    Task::find($id)?->update([
        'text' => $text,
    ]);
}

测试

composer test

变更日志

有关最近更改的更多信息,请参阅 CHANGELOG

贡献

有关详细信息,请参阅 CONTRIBUTING

安全漏洞

有关如何报告安全漏洞的详细信息,请参阅 我们的安全策略

致谢

许可

MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件