改进注册页面来开始本课程。在这里,我们将添加一个按钮来显示 / 隐藏密码,生成一个随机密码,并显示密码强度栏。
原来的注册页是长这样的:
新 Livewire 组件
首先,我们将创建一个 Livewire 组件。
php artisan make:livewire RegisterPasswords
现在,我们需要将 resources/views/auth/register.blade.php 视图中的密码字段移动到新创建的 Livewire 组件。
resources/views/livewire/register-passwords.blade.php:
<div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
<!-- Confirm Password -->
<div class="mt-4">
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
<x-text-input id="password_confirmation" class="block mt-1 w-full"
type="password"
name="password_confirmation" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
</div>
</div>
resources/views/auth/register.blade.php :
<livewire:register-passwords/>
使用 Alpine.js 显示 / 隐藏密码
首先,让我们制作一个密码显示 / 隐藏功能。为此,我们只使用 Alpine.js,不需要 Livewire,因为我们只与浏览器交互,不需要将数据发送到服务器。\
resources/views/livewire/register-passwords.blad.php:
<div class="flex mt-1 mb-2">
<div class="relative flex-1 col-span-4" x-data="{ show: true }">
<input class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
id="password"
:type="show ? 'password' : 'text'"
name="password"
required autocomplete="new-password" />
<button type="button" class="flex absolute inset-y-0 right-0 items-center pr-3" @click="show = !show" :class="{'hidden': !show, 'block': show }">
<!-- Heroicon name: eye -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</button>
<button type="button" class="flex absolute inset-y-0 right-0 items-center pr-3" @click="show = !show" :class="{'block': !show, 'hidden': show }">
<!-- Heroicon name: eye-slash -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" />
</svg>
</button>
</div>
</div>
Alpine 中的所有内容都是从 x-data
指令开始的,所以我们添加了名为 show 的反应数据,默认情况下,我们将其设置为 true。接下来,对于输入,我们绑定 type 属性,将其类型更改为 password 或 text 。
我们有两个按钮,我们使用图标来显示。对于这些按钮,我们使用缩写语法 @click 来更改显示状态。
生成随机密码
现在,让我们添加一个按钮来生成随机密码。
现在,我们可以继续添加按钮。为此,我们需要 Livewire 组件上的两个公共属性来绑定这两个密码字段。
app/Http/Livewire/RegisterPasswords.php:
public string $password = '';
public string $passwordConfirmation = '';
把这两个属性用 wire:model 绑定
resources/views/livewire/register-passwords.blade.php:
<input class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
id="password"
:type="show ? 'password' : 'text'"
name="password"
wire:model.live="password"
required autocomplete="new-password" />
...
<x-text-input id="password_confirmation" class="block mt-1 w-full"
type="password"
wire:model="passwordConfirmation"
name="password_confirmation" required />
让我们添加自动生成密码的按钮\
resources/views/livewire/register-passwords.blade.php:
<div class="flex mt-1 mb-2">
<div class="relative flex-1 col-span-4" x-data="{ show: true }">
...
</div>
<div class="flex items-center place-content-end ml-1">
<x-primary-button wire:click="generatePassword" type="button">随机密码</x-primary-button>
</div>
</div>
这个新按钮有一个名为 generatePassword 的 Livewire 方法。\
app/Http/Livewire/RegisterPasswords.php:
public function generatePassword(): void
{
$lowercase = range('a', 'z');
$uppercase = range('A', 'Z');
$digits = range(0,9);
$special = ['!', '@', '#', '$', '%', '^', '*'];
$chars = array_merge($lowercase, $uppercase, $digits, $special);
$length = 12;
do {
$password = array();
for ($i = 0; $i <= $length; $i++) {
$int = rand(0, count($chars) - 1);
$password[] = $chars[$int];
}
} while (empty(array_intersect($special, $password)));
$this->setPasswords(implode('', $password));
}
private function setPasswords($value): void
{
$this->password = $value;
$this->passwordConfirmation = $value;
}
点击按钮可生成随机密码了
显示密码强度
我们将添加到注册表单的最后一个功能:显示密码强度。为了确定强度,我们将使用 bjeavons/zxcvbn-php 包。
composer require bjeavons/zxcvbn-php
要更新强度值,我们将使用 Livewire Lifecycle Hook 并设置 $strengthScore 公共属性。此外,我们需要在生成密码时更新强度分数。\
现在我们可以在刀刃文件中显示强度值。除了进度条,我们还会用文字写下密码的强度,例如 “弱” 或 “强”。
app/Livewire/RegisterPasswords.php:#
use ZxcvbnPhp\Zxcvbn;
class RegisterPasswords extends Component
{
public string $password = '';
public string $passwordConfirmation = '';
public int $strengthScore = 0;
public array $strengthLevels = [
1 => 'Weak',
2 => 'Fair',
3 => 'Good',
4 => 'Strong',
];
public function updatedPassword($value)
{
$this->strengthScore = (new Zxcvbn())->passwordStrength($value)['score'];
}
// ...
protected function setPasswords($value): void
{
$this->password = $value;
$this->passwordConfirmation = $value;
$this->updatedPassword($value);
}
因为我们只有一个分数的整数值,所以我们将添加一个公共属性,作为单词中哪个分数值对应哪个强度的数组。\
resources/views/livewire/register-passwords.blade.php:
<div class="flex items-center place-content-end ml-1">
<x-primary-button wire:click="generatePassword" type="button">随机密码</x-primary-button>
</div>
</div>
<span class="text-sm">
<span class="font-semibold">密码强度:</span> {{ $strengthLevels[$strengthScore] ?? '弱' }}
</span>
<progress value="{{ $strengthScore }}" max="4" class="w-full"></progress>
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
至此,我们增强了注册表表单。