AlpineJS

未匹配的标注

AlpineJS

在很多情况下,页面交互不能保证完整的服务器往返,例如切换模式。

对于这些情况,AlpineJS 是 Livewire 的完美伴侣。

它允许您以 declarative/reactive 的方式将 JavaScript 行为直接添加到标记中,这应该与 VueJS 非常相似(如果这是您惯用的方式)。

在Livewire中使用Alpine

Livewire 开箱即用地支持 Alpine,并且努力使组合尽可能平滑。

注意:必须安装Alpine才能使用它。 请查看Alpine repo 以获取安装说明。

这是在 Livewire 组件的视图内使用 AlpineJS 进行“下拉”功能的示例。

<div>
    ...

    <div x-data="{ open: false }">
        <button @click="open = true">Show More...</button>

        <ul x-show="open" @click.away="open = false">
            <li><button wire:click="archive">Archive</button></li>
            <li><button wire:click="delete">Delete</button></li>
        </ul>
    </div>
</div>

提取可重复使用的 blade 组件

如果您还不习惯使用每种工具,那么混合使用两种语法可能会有些混乱。

因此,在可能的情况下,您应该将 Alpine 提取到可重复使用的 Blade 组件中,以便在 Livewire(以及应用程序中的任何位置)中使用。

这是一个示例(使用Laravel 7 Blade组件标签语法)。

Livewire 视图:

<div>
    ...

    <x:dropdown>
        <x-slot name="trigger">
            <button>Show More...</button>
        </x-slot>

        <ul>
            <li><button wire:click="archive">Archive</button></li>
            <li><button wire:click="delete">Delete</button></li>
        </ul>
    </x:dropdown>
</div>

可重用的“下拉”blade组件:

<div x-data="{ open: false }">
    <span @click="open = true">{{ $trigger }}</span>

    <div x-show="open" @click.away="open = false">
        {{ $slot }}
    </div>
</div>

现在,Livewire和Alpine语法完全分开,并且您具有可重用的Blade组件,可以与其他组件一起使用。

创建一个DatePicker组件

Livewire中JavaScript的一个常见用例是自定义表单输入。 日期选择器,颜色选择器等之类的东西对于您的应用程序通常是必不可少的。

通过使用上面相同的模式(并添加一些额外的调整),我们可以利用Alpine轻松地与这些类型的JavaScript组件进行交互。

让我们创建一个名为date-picker 的可重复使用的 Blade 组件,我们可以使用它使用 wire:model 将某些数据绑定到Livewire中。

这是我们将如何使用它:

<form wire:submit.prevent="schedule">
    <label for="title">Event Title</label>
    <input wire:model="title" id="title" type="text">

    <label for="date">Event Date</label>
    <x:date-picker wire:model="date" id="date"/>

    <button>Schedule Event</button>
</form>

对于此组件,我们将使用 Pikaday 库。

根据文档,软件包(引入静态资源之后)的最基本用法如下所示:

<input type="text" id="datepicker">

<script>
    new Pikaday({ field: document.getElementById('datepicker') })
</script>

您只需要一个 元素,Pikaday 将为您添加所有额外的日期选择器行为。

现在,让我们看看如何为该库编写可重复使用的Blade组件。

date-picker可重用blade组件:

<input
    x-data
    x-ref="input"
    x-init="new Pikaday({ field: $refs.input })"
    type="text"
    {{ $attributes }}
>

注意:{{$attributes}} 表达式是 Laravel 7 及更高版本中的一种机制,用于转发在组件标签上声明的额外HTML属性。

转发 wire:model input事件

在幕后,每次在元素上或元素下分配 input 事件时,wire:model 都会添加一个事件侦听器以更新属性。 在 Livewire 和 Alpine 之间进行通信的另一种方法是使用 Alpine 调度一个 input 事件,并在其上具有 wire:model 元素的元素内或元素上的一些数据。

让我们创建一个人为设计的示例,其中当用户单击一个按钮时,名为 $foo 的属性设置为bar,而当用户单击另一个按钮时,将 $foo 设置为baz

在Livewire组件的视图内:

<div>
    <div wire:model="foo">
        <button x-data @click="$dispatch('input', 'bar')">Set to "bar"</button>
        <button x-data @click="$dispatch('input', 'baz')">Set to "baz"</button>
    </div>
</div>

一个更真实的示例将创建一个“颜色选择器” Blade组件,该组件可能会在Livewire组件中使用。

Color-picker 组件用法:

<div>
    <x:color-picker wire:model="color"/>
</div>

对于组件定义,我们将使用名为Vanilla Picker的第三方颜色选择器库。

本示例假定您已将其加载到页面上。

Color-Picker blade 组件定义(未注释):

<div
    x-data="{ color: '#ffffff' }"
    x-init="
        picker = new Picker($refs.button);
        picker.onDone = rawColor => {
            color = rawColor.hex;
            $dispatch('input', color)
        }
    "
    wire:ignore
    {{ $attributes }}
>
    <span x-text="color" :style="`background: ${color}`"></span>
    <button x-ref="button">Change</button>
</div>

Color-picker blade 组件定义 (注释):

<div
    x-data="{ color: '#ffffff' }"
    x-init="
        // 单击“更改”按钮时,连线以显示选择器。
        picker = new Picker($refs.button);
        // 每次选择新颜色时都运行此回调。
        picker.onDone = rawColor => {
            // 设置Alpine的“颜色”属性。
            color = rawColor.hex;
            // 分配 color属性供 'wire:model' 使用。
            $dispatch('input', color)
        }
    "
    // Vanilla Picker 会将自己的DOM附加到此元素中,因此我们需要添加 `wire:ignore` 来告诉 Livewire 跳过DOM区分。 
    wire:ignore
    // 转发添加到组件标签的所有属性,例如 `wire:model = color`
    {{ $attributes }}
>
    <!-- 在将背景色设置为所选颜色的情况下显示当前颜色值。 -->
    <span x-text="color" :style="`background: ${color}`"></span>
    <!-- 单击此按钮时,将显示颜色选择器对话框。-->
    <button x-ref="button">Change</button>
</div>

忽略DOM更改(使用wire:ignore

幸运的是,像 Pikaday 这样的库在页面末尾添加了额外的 DOM。 许多其他库在初始化后便会立即操作 DOM,并在与它们交互时继续对 DOM 进行更改。

发生这种情况时,Livewire 很难跟踪要在组件更新中保留哪些DOM操作以及要丢弃哪些DOM操作。

要告诉Livewire 忽略组件中HTML子集的更改,可以添加 wire:ignore 指令。

Select2 库是接管DOM一部分的那些库之一(它用大量的自定义标记替换了 <select> 标签)。

这是一个在Livewire组件中使用Select2库的示例,以演示 wire:ignore 的用法。

<div>
    <div wire:ignore>
        <select class="select2" name="state">
            <option value="AL">Alabama</option>
            <option value="WY">Wyoming</option>
        </select>

        <!-- Select2 will insert it's DOM here. -->
    </div>
</div>

@push('scripts')
    <script>
        $(document).ready(function() {
            $('.select2').select2();
        });
    </script>
@endpush

另外,请注意,有时忽略元素的更改(而不是其子元素)会很有用。 在这种情况下,您可以将 self 修饰符添加到 wire:ignore 指令中,例如:wire:ignore.self.

在Livewire和JavaScript之间进行通信

浏览器页面上加载的每个Livewire组件都具有唯一的ID和相应的JavaScript对象。

您可以使用以下语法检索此JavaScript对象:let component = window.livewire.find('some-component-id')

现在有了组件对象,您实际上可以从JavaScript以编程方式与其进行交互。

例如,给定以下Livewire组件:

CreatePost

use Livewire\Component;

class CreatePost extends Component
{
    public $title = '';

    public function create()
    {
        Post::create(['title' => $this->title]);
    }

    public function render()
    {
        return view('livewire.create-post');
    }
}

create-post.blade.php

<form wire:submit.prevent="create">
    <input wire:model="title" type="text">

    <button>Create Post</button>
</form>

如果您偶然知道在浏览器中加载该组件时分配给该组件的唯一组件ID,则可以在DevTools中运行以下命令(或从页面上的任何JavaScript运行):

<script>
    let component = window.livewire.find('the-unique-component-id')

    var title = component.get('title')
    // 获取 `public $title` 组件属性的当前值。
    // 默认为“”,因此“ title”最初将设置为空字符串。

    component.set('title', 'Some Title')
    // 将 public $title 组件属性设置为 “ Some Title”
    // 您实际上会在页面的输入字段中看到“Some Title”。 
    // 对于Livewire,调用此方法与实际在输入字段中键入之间没有区别。

    component.call('create')
    // 这将完全在组件上调用“ create”方法,就好像您在窗体上单击物理按钮一样。
</script>

如果可以跟随,那么您应该能够在这里看到潜力。 该API允许您通过JavaScript以编程方式与Livewire组件进行交互。 这种模式释放了各种潜力。

您可能想知道,“但是如何获得唯一的组件ID?”。 好了,您可以检查源代码并查看组件根元素上的wire:id属性。 或者,您可以从Livewire组件的视图内部使用以下非常方便的语法:

<div>
    <input x-data @input.keydown.enter="@this.set('foo', 'bar')">
</div>

如果您遵循的话,Livewire会有一个名为@this 的Blade指令,它是window.livewire.find('...')的别名。 该指令使从 JavaScript(特别是AlpineJS表达式)与当前Livewire组件的通讯变得非常容易。

如果您要在浏览器中检查渲染页面的源,则输入元素将如下所示:

<input x-data @input.keydown.enter="window.livewire.find('unique-id').set('foo', 'bar')">

如您所见,Livewire和Alpine组合非常强大且富有表现力。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 0
发起讨论 只看当前版本


暂无话题~