Laravel Blade组件
#php #laravel #blade

Laravel Blade是一个强大的模板引擎,可让开发人员在Laravel应用程序中创建动态和可重复使用的视图。刀片的关键特征之一是能够创建可重复使用的组合组件,这可以帮助加快前端开发。通过启用可重复使用的组件来提供一致的样式和行为,开发人员可以避免需要从头开始构造元素。相反,他们可以简单地利用已经存在的组件。

在本文中,我们将创建一个基本形式,向您展示刀片组件的一些好处和技术。

创建您的第一个组件

有两种类型的组件:基于类和匿名的组件。基于类的组件具有类和视图模板,而匿名组件仅具有视图模板。在大多数情况下,匿名组件就足够了,我只有在需要使用依赖注入时才倾向于使用基于类的组件。

php artisan make:component layouts.app --view

运行上述命令将创建我们的第一个组件,一个名为Resources/views/components/layouts/app.blade.php的布局文件。该文件将是应用程序的布局。

<!-- /resources/views/components/layouts/app.blade.php -->

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Laravel Blade Components</title>

    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
    {{ $slot }}
</body>
</html>

<!-- /resources/views/example.blade.php -->

<x-layouts.app>
    Hello World!
</x-layouts.app>

{{ $slot }}将渲染我们传递给它的任何东西。例如,通过Hello World!将在页面上渲染。插槽是使刀片组件可组合的原因。我们可以将组件传递给其他组件,甚至可以使用named slots

创建一个表单

运行以下以创建我们的匿名索引组件

php artisan make:component form.index --view

通常,要将组件组合在一起,您必须具有一个表单组件,然后将其余的表单组件在文件夹中。

/resources/views/components/form.blade.php
/resources/views/components/form/group.blade.php

匿名索引组件允许您将组件分组在一起。

/resources/views/components/form/index.blade.php
/resources/views/components/form/group.blade.php

用法看起来像

<x-layouts.app>
    <x-form>
        <x-form.group>
            Hello!
        </xform.group>
    </x-form>
</x-layouts.app>
<!-- /resources/views/components/form/index.blade.php -->

@props([
    'method' => 'POST',
    'action',
    'hasFiles' => false,
])

<form
    method="{{ $method !== 'GET' ? 'POST' : 'GET' }}"
    action="{{ $action }}"
    {!! $hasFiles ? 'enctype="multipart/form-data"' : '' !!}
    {{ $attributes->except(['method', 'action']) }}
>
    @csrf
    @method($method)

    {{ $slot }}
</form>

我们定义了要组件接受的道具。我们能够设置一些明智的默认值。大多数表单作为POST的方法,因此我们将其设置为默认情况。当表单发送文件时,我们需要具有enctype属性。而不是每次使组件都添加此属性时,而不是在需要时输入。

我们要确保开发人员在使用此组件时通过操作通过操作,以便我们将操作设置为道具,但没有设置默认值。如果不通过诉讼,laravel如果我们不进行isset()检查,则会丢下错误。

回音$attributes允许我们传递我们需要的任何其他属性,而无需在道具中定义它们。

<x-form action="/users"></x-form>
<x-form :action="route('users.store')"></x-form>

<x-form method="GET"></x-form>

<x-form has-files></x-form>

<x-form class="border border-red-200"></x-form>

<x-form 
    :action="route('photos.store')"
    has-files
    class="p-5"
>
    //
</x-form>

在上面的示例中,我们使用:action属性。我们使用:前缀表示它是PHP表达式或变量。我们也可以做:action="$someRoute"。如果它是一个硬编码或原始值,我们会像普通一样做action="/"

创建文本输入

使用输入时,我喜欢创建一个可以使用输入组件的组组件。该组将显示标签,帮助文本和任何错误。

php artisan make:component input.group --view

在这里,我们使用$attributes->class(['block'])设置默认类。如果要通过类属性,则任何类都将与块合并。

我们使用@class()进行有条件设置类。始终显示text-gray-700 inline-block mb-1,在存在$error时,text-red-500仅合并到默认值中。

如果我们没有通过道具,则未定义,这就是为什么我们使用@isset($help)@isset($error)检查它们是否设置的原因。我们还可以将道具设置为将null作为其默认值并进行检查。

<!-- /resources/views/components/input/group.blade.php -->

@props([
    'label',
    'for',
    'help',
    'error',
])

<label
    {{ $attributes }}
    {{ $attributes->class(['block']) }}
    for="{{ $for }}"
>
    <span
        @class([
            'text-gray-700 inline-block mb-1',
            'text-red-500' => isset($error)
        ])
    >{{ $label ?? '' }}</span>
    <div class="mt-1">
        {{ $slot }}
    </div>
    @isset($help)
        <p class="mt-2 text-sm text-gray-500" id="{{ $for }}">{{ $help }}</p>
    @endif
    @isset($error)
        <div class="mt-1 text-red-500 text-sm">{{ $error }}</div>
    @endif
</label>

接下来我们将创建一个文本输入

php artisan make:component input.text --view

此组件使用@aware()。这允许儿童组成部分access data in the parent component

<!-- /resources/views/components/input/text.blade.php -->

@aware([
    'error',
])

@props([
    'value',
    'name',
    'for',
])

<input
    {{ $attributes->class([
        'shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md',
        'border-red-500' => $error
    ]) }}
    @isset($name) name="{{ $name }}" @endif
    type="text"
    @isset($value) value="{{ $value }}" @endif
    {{ $attributes }}
/>

创建按钮

最后,我们可以创建一个按钮来提交表格。我们将再次使用匿名索引组件。这是因为我不想直接访问该按钮,而是想在primarysecondary按钮中使用此组件。

php artisan make:component button.index --view

<!-- /resources/views/components/button/index.blade.php -->

@aware([
    'type',
])

<button
    type="{{ $type }}"
    {{ $attributes->class([
        'inline-flex items-center border font-medium rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2',
    ]) }}
>
    {{ $slot }}
</button>

接下来,我们创建我们的primary按钮。您可以看到我们正在使用primary组件中的x-button

php artisan make:component button.primary --view
<!-- /resources/views/components/button/primary.blade.php -->

@props([
    'type' => 'button',
])

<x-button
    {{ $attributes->merge(['class' => 'border-transparent shadow-sm text-white bg-indigo-600 hover:bg-indigo-700']) }}>
    {{ $slot }}
</x-button>

x-button组件分开意味着我们可以在多个位置重复使用它,即使是单独使用它。

将所有这些放在一起

现在,我们创建了我们的组件,我们可以开始一起使用它们。我们首先使用表单组件包装所有输入,在这种情况下,我们只需要通过路由作为操作。接下来,我们有几个输入组,这些输入组为标签,一个错误和错误。错误来自所有视图可用的validation error bag。传递给输入组插槽是输入。在此示例中,我们使用自动属性将旧值传递给值属性。最后,我们使用按钮提交表格。

<x-form :action="route('users.store')">
    <x-input.group label="Email" for="email" :error="$errors->first('email')">
        <x-input.email name="email" :value="old('email')" />
    </x-input.group>
    <x-input.group label="Password" for="password" :error="$errors->first('password')">
        <x-input.password name="password" :value="old('password')" />
    </x-input.group>
    <x-button.primary>
      Submit
    </x-button.primary>
</x-form>

我们也可以将刀片组件与普通的HTML混合。

<x-form action="/photo" has-files>
    <div class="p-3 border border-slate-200">
      <x-input.group label="Password" for="photo" :error="$errors->first('photo')">
          <input type="file" name="photo" />
      </x-input.group>
      <button>Submit</button>
    </div>
</x-form>

奖励提示

Short Attribute Syntax

{{-- Short attribute syntax... --}}
<x-input.text $name />

{{-- Is equivalent to... --}}
<x-input.text name="{{ $name }}" />

Named Slots-您可以通过给组件中的名称在组件中具有多个插槽。

<x-modal>
    <x-slot:header>
      Hello World!
    </x-slot>

    Some lovely content

    <x-slot:footer>
      Goodbye World!
    </x-slot>
</x-modal>

您通过以下来实现这一目标

<!-- /resources/views/components/modal/index.blade.php -->

<div>
  <header>
    {{ $header }}
  </header>
  <main>
    {{ $slot }}
  </main>
  <footer>
    {{ $footer }}
  </footer>
</div>