Livewire v3 新特性和更新
上周三在 Laracon 线上大会, Caleb Porzio 进行了一个名为"Livewire 的未来"的演讲,展示了 Livewire v3 计划带来的新特性。本文将和大家一起探讨这些特性。
基于 Alpine 的全新内核
Livewire 对整个内核都进行了重写。新内核对 Alpine 依赖更多,使用 Morph、History 及其他其驱动的插件,这意味着 Livewire 有了更好的 diffing、特性,可以编译得更快,Livewire 和 Alpine 之间的重复也会更少。
同时也带来了一些新的特性。
Livewire scripts、 styles 和 Alpine 自动注入
使用 Composer 安装 Livewire v2 后,你需要手动添加 @livewireStyles, @livewireScripts 及 Alpine 到你的布局中。而对于 Livewire v3,你只需安装 Livewire,其他步骤会被自动注入,包括 Alpine!
<!DOCTYPE html>
<html lang="en">
<head>
<script src="//unpkg.com/alpinejs" defer></script>
@livewireStyles
@livewireScripts
</head>
<body>
...
</body>
</html>
热加载无需编译
Livewire v3 会包含无需 bulid 热加载的功能。只需在编辑器中保存文件,可以在不用破坏组件状态的情况下,马上在浏览器中看到对应的变化!
wire:transition
Alpine 有 transition 有了一段时间了, Livewire v3 将有一个叫 wier:transition 的组建,对 x-transition 进行包装使用。可以将 wire:transition 添加到任何要展示或者隐藏的元素中。由于 wire:transition 底层使用的是 x-transition,因此也支持像 .opacity 和 .duration 这样的修饰符。
在 PHP 类中写 JavaScript 函数
Livewire v3 支持直接在后端 Livewire 组件中直接写 JavaScript 函数。要添加 js 函数到组件,要在函数上面加上 /** @js */ 注释,然后使用 PHP HEREDOC 语法返回 JavaScript 代码,并在前端调用。JavaScrpt 代码无需发送任何请求到后端即可执行。
<?php
namespace App\Http\Livewire;
class Todos extends \Livewire\Component
{
/** @prop */
public $todos;
/** @js */
public function clear()
{
return <<<'JS'
this.todo = '';
JS;
}
}
<div>
<input wire:model="todo" />
<button wire:click="clear">Clear</button>
</div>
/** @locked */ 属性
Livewire v3 将支持锁定(loced)属性 - 即不能从前端更新的属性。在组件的属性上方添加 /** @locked / 注释,如果有人尝试通过前端更新属性,Livewire 会抛出异常。
<?php
namespace App\Http\Livewire;
class Todos extends \Livewire\Component
{
/** @locked */
public $todos = [];
}
wire:model 默认延迟加载
Livewire 第一版发行时,主要目的在于以真正实时的感觉编写像搜索那样的组件,因此每次输入改变的时候自动发送更新到服务器就显得合理。而现在,我们用 Livewire 构建各种各样的应用。随着 Livewire 及其用法的改进,我们意识到对于 95% 的表单而言 ”deferred" 延迟加载行为是合理的,因此在 V3 中 deferred 功能变成了默认。这能够减少发送到服务器的非必要请求并改善性能。
如果输入框需要“实时(live)”功能,你可以使用 wire:model.live 启用该功能。
注意:这是 v2 升级到 v3 的破坏性改变。
批量请求
在 Livewire v2 中,如果你有多个组件使用 wire:poll 或发送\监听事件,这些组件每个都会单独发送请求到服务器。在 Livewire v3 中,有智能的批量请求,因此wire:poll、事件、监听或者方法调用时,如果有需要可以并入一个请求,减少请求发送量改善性能。
查询属性
在Livewire v2中使用嵌入组件时,如果父组件的属性更新了,子组件的数据不会自动同步。虽然可以使用事件监听手动解决,不过不是很理想。对于 v3,如果需要发送数据给子组件,在子组件属性上面添加 /** @prop */ 注释,然后在父组件中更新,子组件就会自动更新。
<?php
namespace App\Http\Livewire;
class TodosCount extends \Livewire\Component
{
/** @prop */
public $todos;
public function render()
{
return <<<'HTML'
<div>
Todos: {{ count($todos) }}
</div>
HTML;
}
}
/** @modelable */ 属性
Livewire v2 的另一个痛点是,从父组件"modelling" 属性到子组件。比如说你需要一个<livewire:todo-input /> 组件。要传入一个值并使其值在子组件中改变时,在父组件中自动更新,是不容易的事。在 V3 中,你可以在使用该组件使添加 wire:model,然后在该组件内部,添加一个 /** @modelable */ 注释到你储存相应数据的属性上面,剩下的就交给 Livewire 处理。
<?php
namespace App\Http\Livewire;
class Todos extends \Livewire\Component
{
public $todo = '';
public $todos = [];
public function add() ...
public function render()
{
return <<<'HTML'
<div>
<livewire:todo-input wire:model="todo" />
<ul>
@foreach ($todo as $todos)
<li>{{ $todo }}</li>
@endforeach
</ul>
</div>
HTML;
}
}
<?php
namespace App\Http\Livewire;
class TodoInput extends \Livewire\Component
{
/** @modelable */
public $value = '';
public function render()
{
return <<<'HTML'
<div>
<input wire:model="value">
</div>
HTML;
}
}
使用 $parent 访问父组件的数据和方法
Livewire v3 中将会有一个访问父组件数据和方法的新方式。可以使用 $parent 属性访问调用父组件的方法。
<?php
namespace App\Http\Livewire;
class TodoInput extends \Livewire\Component
{
/** @modelable */
public $value = '';
public function render()
{
return <<<'HTML'
<div>
<input
wire:model="value"
wire:keydown.enter="$parent.add()"
>
</div>
HTML;
}
}
@teleport
Livewire v3 也引入了新的 @teleport 模板指令,让你可以传送一小段代码,并在其他DOM 组件中渲染。这个功能有时可以在使用modal模态框及sildeout滑块中避免z-index问题。
<div>
<button wire:click="showModal">Show modal</button>
@teleport('#footer')
<x-modal wire:model="showModal">
<!-- ... -->
</x-modal>
@endteleport
</div>
惰性组件
Livewire v3 将引入惰性组件。有些组件可能因为耗时的查询或者在不总是打开的slideout滑块中渲染而需要花费一些时间,你可能需要一直等到它渲染完。在 Livewire v3 中,只需在渲染的组件中添加一个 lazy 属性,它就不会一开始就被渲染。当它进入视窗后,Livewire 会发送请求去渲染。你也可以在组件中实现 placeholder 方法添加一些占位内容。
<div>
<button wire:click="showModal">Show modal</button>
@teleport('#footer')
<x-modal wire:model="showModal">
<livewire:example-component lazy />
</x-modal>
@endteleport
</div>
<?php
namespace App\Http\Livewire;
class ExampleComponent extends \Livewire\Component
{
public static function placeholder()
{
return <<<'HTML'
<x-spinner />
>>>
}
public function render() /** [tl! collapse:7] */
{
return <<<'HTML'
<div>
Todos: {{ count($todos) }}
</div>
HTML;
}
}
wire:navigate
在 Livewire v3,你可以将 wire:navigate 添加到任何的<a>标签中,当点击时,Livewire 会在后台获取该页面,然后迅速将 DOM 交给你的应用,像SPA单页应用一样。 如果你也添加了 .prefetch 修饰符,Livewire 会预先获取链接内容,使之更快。
<a href="/example" wire:navigate.prefetch>Example Page</a>
@persist
V3 引入的另外一个很酷的模板指令是 @persist。与wire:navigation 一起联合使用 @persist,能让你应用的一部分在页面改变时保持不变。比如podcast播放器可以在你页面切换的时候继续保持播放。
<!DOCTYPE html>
<html lang="en">
<body>
<x-podcast-header />
<x-podcast-body>
{{ $slot }}
</x-podcast-body>
@persist('player')
<x-podcast-player />
@endpersist
</body>
</html>
新的 laravel-livewire.com 网站设计
Livewire 网站和文档也进行了全新的设计!