Livewire v3 已发布
发布于 作者: Jason Beggs
Caleb Porzio 刚刚发布了官方 Livewire v3! 在他在 Laracon 的演讲中,他演示了许多新功能,其中一些我们将在这里介绍,您可以观看完整视频
重写的核心
Livewire 的核心已从头开始完全重写。 重写核心是一项艰巨的任务,但这是完成此版本中包含的所有内容所必需的。 新的核心架构也将更容易维护 Caleb 和 Livewire 核心贡献者。
Alpine 利用
v3 核心现在充分利用了 Alpine。 Livewire v3 不再包含用于应用 DOM 更新、添加事件侦听器等的代码,而是利用 Alpine 来完成繁重的工作。 通过注册 Alpine 插件,Livewire 现在允许 Alpine 完成繁重的工作,同时仍然提供您所喜爱的语法糖。
这也意味着 Alpine 现在默认包含在 Livewire 中,因此无需通过 CDN 或 NPM 加载 Alpine。 它被自动注入。
此外,v3 利用 Alpine Morph 插件来比较 DOM 并应用更新,而不是 morphdom。 这将导致更少的 DOM 比较问题,并总体上提高 Livewire 和 Alpine 之间的兼容性。
改进的组件嵌套
过去,我认为嵌套 Livewire 组件是一种反模式,或者在可能的情况下要避免,因为存在潜在的性能影响。 在 v3 中,情况不会这样!
借助响应式属性、捆绑请求、新的 $parent
属性和其他改进,v3 在很大程度上改进了组件嵌套。 我们将在本文的后面更详细地介绍其中一些改进。
改进的属性序列化
v2 试图智能地确定初始渲染时属性的类型,以便在后续请求中将它们重新水化为相同的类型。 然而,v2 不支持深度嵌套的水化。 如果您的集合包含混合类型,v2 不会将每个集合项转换回其原始类型。 v3 对此更加智能,它存储每个项目的类型,以便它可以在后续请求中将它们转换回正确的类型。
捆绑请求
在 v2 中,当页面上的多个组件轮询或侦听同一个事件时,Livewire 会在每次需要与服务器通信时发送每个组件的单独请求。 v3 的效率更高,它将所有这些更新捆绑到一个请求中。
更好的默认值
Blade 标记注入
DOM 比较是您在 v2 中遇到的最常见问题之一。 该问题通常是由 @if
和类似的 Blade 指令导致的,这些指令插入或删除 DOM 元素。 v3 试图通过在这些 Blade 指令开始和结束的地方注入 HTML 注释(标记)来规避这些问题。 通过查找这些标记,Livewire 可以将新的或删除的 DOM 元素与标记匹配起来,以便将它们正确地放置在 DOM 中。
<form wire:submit="save"> {{-- ... --}} <!-- __BLOCK__ --> @if ($success) <div>Saved!</div> @endif <!-- ENDBLOCK --> <div> <button>Save</button> </div><div>
wire:model
默认情况下是延迟的
最初,Livewire 作为“实时”功能非常酷,因此它成为默认设置。 经过深思熟虑并观察实际使用情况后,Caleb 意识到延迟 wire:model
请求是更好的默认设置。 大多数应用程序实际上不需要在每次按键时将输入值与服务器同步,因此 v3 翻转了默认行为。 使用 wire:model
时,以前 wire:model.defer
功能是新的默认行为。 已添加 wire:model.live
来替换实际需要“实时”的输入上的旧默认行为。
{{-- Now deferred by default --}}<input wire:model="name"> {{-- Syncs with the server on every keystroke --}}<input wire:model.live="name">
新功能
自动注入的资产
在 v3 中,Livewire 自动注入其样式、脚本和 Alpine。 您不再需要添加 <livewire:styles />
和 <livewire:scripts />
或者在您的项目中加载 Alpine!
新的默认命名空间
默认情况下,v3 使用 App\Livewire
命名空间(和 app/Livewire
目录),而不是 App\Http\Livewire
。 如果您更喜欢旧的命名空间,有一个配置选项可以保留它。
响应式属性
来自 React 和 Vue 等前端框架的一些 Livewire 用户自动假设他们传递给嵌套组件的属性将对父组件中的更改做出反应。 由于 v2 中的一些限制,这实际上是不可能的。 我们必须依靠事件或其他变通方法来同步嵌套组件。 v3 添加了对“响应式”属性的支持。 只要在您的组件类中的属性上添加一个 #[Reactive]
PHP 属性即可。
<?php // ...use Livewire\Attributes\Reactive; class InvoiceItem extends Component{ #[Reactive] public $item;}
表单对象
表单对象是一个新概念,可以通过抽象一些与表单相关的代码来帮助保持组件类整洁。 您可能希望将组件的表单属性、验证、保存功能等放在表单对象上。
这是一个小例子,但我建议您阅读文档以了解所有功能的完整列表!
<?php namespace App\Livewire\Forms; use Livewire\Form; class UserForm extends Form{ #[Rule('required')] public $name = ''; #[Rule(['required', 'email'])] public $email = '';}
<?php namespace App\Livewire; use Livewire\Component;use App\Models\Post;use App\Livewire\Forms\UserForm; class UpdateProfile extends Component{ public UserForm $form; public function save() { auth()->user()->update( $this->form->all() ); return $this->redirect('/profile'); } public function render() { return view('livewire.update-profile'); }}
<form wire:submit="save"> <input type="text" wire:model="form.name"> <div> @error('form.name') <span class="error">{{ $message }}</span> @enderror </div> <input type="email" wire:model="form.email"> <div> @error('form.email') <span class="error">{{ $message }}</span> @enderror </div> <button type="submit">Save</button></form>
wire:navigate
(SPA 模式)
另一个新增功能是 wire:navigate
。 当使用全页面 Livewire 组件时,您现在可以将 wire:navigate
属性添加到您的链接中以启用类似 SPA 的体验。 Livewire 不会执行全页面加载,而是会将一个加载指示器添加到页面顶部,在后台获取新页面的内容,然后智能地交换页面上的 HTML。 此功能还支持预取和重定向,并使持久化元素成为可能。
<a href="/profile" wire:navigate>Profile</a>
@persist
随着 wire:navigate
的添加,您现在可以拥有在浏览不同页面时不会重新加载的“持久化”元素。 此功能将非常适合音频播放器等用例,您希望在用户点击不同页面时继续播放音频。
要使用此功能,请将您要持久化的元素包装在 @persist
指令中
@persist('player') <audio src="{{ $episode->file }}" controls></audio>@endpersist
延迟加载的组件
Livewire 现在支持延迟加载的组件。 有时,您有一个组件可能会减慢初始页面加载速度,或者最初隐藏在您想要延迟加载以保持初始页面加载速度快的模态中。
要延迟加载组件,请在您的 Blade 中的组件上添加 lazy
属性。
<livewire:your-component lazy />
Livewire 将在初始页面加载时跳过渲染该组件。在所有其他内容加载完成后,将发送网络请求以完全渲染该组件,并将该组件插入 DOM。
$parent
属性
为了与早期 Livewire 版本中的“父”组件进行通信,您必须使用事件和侦听器。在 v3 中,有一个新的 $parent
属性,您可以使用它从子组件直接调用父组件的方法。
<div> <span>{{ $item->name }}</span> <button wire:click="$parent.remove({{ $item->id }})">Remove</button></div>
混合方法/从后端评估 JS
v3 允许您现在在后端组件中编写 JavaScript 方法。通过在组件上的方法中添加 #[Js]
属性,您可以将 JavaScript 代码编写为字符串,Livewire 将公开该方法供您的前端使用。当通过 wire:click
调用时,JavaScript 将在前端执行,无需将网络请求发送回服务器。
<?php // ...use Livewire\Attributes\Js; class UsersTable extends Component{ public $filters = []; #[Js] public function reset() { return <<<'JS' $wire.filters = []; JS; } // ...}
<div> <div> <input wire:model.live="filters.active" type="checkbox"> <label>Only active</label> </div> <button wire:click="reset">Reset Filters</button> @foreach ($users as $user) {{-- ... --}} @endforeach</div>
有时,从后端方法执行一小段 JavaScript 代码很有用。v3 通过 $this->js()
方法使之成为可能。只需调用该方法并传递 JavaScript 字符串,Livewire 将在下一次渲染时在前端执行它。
public function save(){ // ... $this->js("alert('You just executed JS from the backend!')");}
PHP 属性用法
PHP 属性是 PHP 的一项相对较新且强大的功能,Livewire v3 在新功能和现有功能中广泛使用它们。
#[Url]
新的 #[Url]
属性替换了 v2 中的 $query
属性。在组件的任何属性上方添加 #[Url]
,它将在查询字符串中进行跟踪。
<?php // ...use Livewire\Attributes\Url; class UsersTable extends Component{ #[Url] public $filters = []; // ...}
#[On]
新的 #[On]
属性替换了 v2 中的 $listeners
属性。在组件上的方法上方添加 #[On('some-event')]
,并在调度该事件时执行它。
<?php // ...use Livewire\Attributes\Url; class UsersTable extends Component{ // ... #[On('filters-reset')] public function resetFilters() { // ... }}
#[Layout]
和 #[Title]
新的 #[Layout]
和 #[Title]
属性允许您为全页面组件设置布局视图和标题。它们可以添加到组件的 render
方法或类本身中。
#[Layout('layouts.app')]public function render(){ return view('livewire.create-post');}
#[Computed]
我们有 #[Computed]
属性,它取代了 v2 中用于计算属性的 getSomeProperty
语法。它的功能与旧语法相同,但有一些新的、非常强大的补充。
在 v2 中,计算属性只能在单个请求期间进行缓存。在 v3 中,您可以跨多个请求甚至跨多个组件缓存属性。这将使缓存昂贵的数据库查询变得轻而易举!
use Livewire\Attributes\Computed; // Cache across requests#[Computed(persist: true)]public function user(){ return User::findOrFail($this->userId);} // Cache across all instances of this component#[Computed(cache: true)]public function user(){ return User::findOrFail($this->userId);}
#[Rule]
新的 #[Rule]
属性替换了 v2 中的 $rules
属性和 rules
方法。在组件上的属性中添加 #[Rule(['required', 'max:150'])]
,以告知 Livewire 属性应如何验证。
<?php // ...use Livewire\Attributes\Rule; class InvoiceItem extends Component{ #[Rule(['required', 'max:120'])] public $itemName; // ...}
#[Locked]
新的 #[Locked]
属性允许您防止用户从前端更新属性。您可以将其用作对用户不应更改的属性的安全措施。
<?php // ...use Livewire\Attributes\Locked; class InvoiceItem extends Component{ #[Locked] public $id; // ...}
升级
大多数应用程序的升级过程将非常快。在 beta 版中包含一个 livewire:upgrade
artisan 命令,可以帮助您进行一些更繁琐的更改,然后您可以按照 升级指南 确保所有内容都已更新。
如果您希望将升级留给 Livewire 专家,Caleb 和我提供了一项服务,可以帮助您快速开始升级过程。您可以在 此处 查看。
新网站设计和域名
除了所有新功能和改进之外,Livewire 文档网站已经完全重新设计、重建和重写!
新文档比 v2 文档更全面。它们详细介绍了每个功能,并深入探讨了 Livewire 如何在幕后处理水合、变形和嵌套组件。我建议您在有时间的情况下通读整个网站。它是一门构建 Livewire v3 应用程序的精通课程!
另一个重大公告是文档网站将迁移到 livewire.laravel.com。去看看吧!
这是一篇很长的文章,但有很多新功能需要介绍!希望您能尽快尝试 v3,并随时就改进提供反馈。
TALL 堆栈(Tailwind CSS、Alpine.js、Laravel 和 Livewire)顾问,也是 designtotailwind.com 的所有者。