Blade Components

ایجاد کامپوننت‌های قابل استفاده مجدد در Blade

graph TD A[Component Usage] --> B{Type?} B -->|Anonymous| C[View File Only] B -->|Class-based| D[Component Class] D --> E[View File] C --> F[Render] E --> F G[Props] --> C G --> D H[Slots] --> C H --> D

Blade Components به شما امکان می‌دهند کامپوننت‌های قابل استفاده مجدد ایجاد کنید که می‌توانند در viewهای مختلف استفاده شوند. این الگو کد را modular و maintainable می‌کند.


انواع Blade Components:


1. Anonymous Components: کامپوننت‌های بدون کلاس که فقط view file دارند. ساده‌تر و سریع‌تر برای کامپوننت‌های ساده.


2. Class-based Components: کامپوننت‌های مبتنی بر کلاس که logic و data manipulation دارند. برای کامپوننت‌های پیچیده‌تر.


مزایای Components:


  • استفاده مجدد در چند view
  • کد تمیزتر و organized‌تر
  • مدیریت بهتر UI elements
  • Props برای passing data
  • Slots برای dynamic content
  • Attributes merging برای HTML attributes
  • Event handling
  • State management

ویژگی‌های پیشرفته:


  • <strong>Props</strong>: دریافت data از parent
  • <strong>Slots</strong>: محتوای dynamic
  • <strong>Named Slots</strong>: چند slot با نام‌های مختلف
  • <strong>Attributes</strong>: HTML attributes merging
  • <strong>Events</strong>: Event handling
  • <strong>Computed Properties</strong>: محاسبه properties
  • <strong>Lifecycle Hooks</strong>: hooks برای component lifecycle

مثال‌ها

Anonymous Component

<!-- resources/views/components/alert.blade.php -->
<div class="alert alert-{{ $type }}">
    {{ $message }}
</div>

<!-- Usage -->
<x-alert type="error" message="Something went wrong!" />

<!-- With default props -->
<!-- In component -->
@props(['type' => 'info', 'message' => ''])

<div class="alert alert-{{ $type }}">
    {{ $message }}
</div>

استفاده از یک کامپوننت anonymous با props.

Class-based Component

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    public function __construct(
        public string $type = 'info',
        public string $message = '',
        public bool $dismissible = false
    ) {}
    
    public function render()
    {
        return view('components.alert');
    }
    
    public function alertClass(): string
    {
        return match($this->type) {
            'error' => 'alert-danger',
            'success' => 'alert-success',
            'warning' => 'alert-warning',
            default => 'alert-info'
        };
    }
}

<!-- Usage -->
<x-alert type="error" message="Error occurred" :dismissible="true" />

ایجاد یک کامپوننت مبتنی بر کلاس.

Component با Slots

<!-- resources/views/components/card.blade.php -->
<div class="card">
    @if(isset($header))
        <div class="card-header">
            {{ $header }}
        </div>
    @endif
    
    <div class="card-body">
        {{ $slot }}
    </div>
    
    @if(isset($footer))
        <div class="card-footer">
            {{ $footer }}
        </div>
    @endif
</div>

<!-- Usage -->
<x-card>
    <x-slot name="header">
        <h2>Card Title</h2>
    </x-slot>
    
    Card content here
    
    <x-slot name="footer">
        <button>Action</button>
    </x-slot>
</x-card>

استفاده از slots برای dynamic content.

Attributes Merging

<!-- resources/views/components/button.blade.php -->
@props(['type' => 'button', 'variant' => 'primary'])

<button 
    type="{{ $type }}"
    {{ $attributes->merge(['class' => 'btn btn-' . $variant]) }}
>
    {{ $slot }}
</button>

<!-- Usage -->
<x-button variant="danger" class="custom-class" id="submit-btn">
    Submit
</x-button>

<!-- Renders: -->
<!-- <button type="button" class="btn btn-danger custom-class" id="submit-btn">Submit</button> -->

Attributes merging برای HTML attributes.

Component با Data

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class UserList extends Component
{
    public function __construct(
        public $users,
        public bool $showEmail = true
    ) {}
    
    public function userCount(): int
    {
        return $this->users->count();
    }
    
    public function render()
    {
        return view('components.user-list');
    }
}

<!-- Usage -->
<x-user-list :users="$users" :show-email="false" />

Component با data و computed properties.

Inline Components

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    public function __construct(
        public string $type,
        public string $message
    ) {}
    
    public function render()
    {
        return <<<'blade'
        <div class="alert alert-{{ $type }}">
            {{ $message }}
        </div>
        blade;
    }
}

Inline component که view file ندارد.

Component Namespaces

<?php

// In AppServiceProvider
use Illuminate\Support\Facades\Blade;

Blade::componentNamespace('App\View\Components\Forms', 'forms');

// Usage
<x-forms::input name="email" type="email" />

// Or in package
Blade::componentNamespace('Vendor\Package\View\Components', 'package');

// Usage
<x-package::component />

Component namespaces برای organization بهتر.

Dynamic Components

<!-- Dynamic component selection -->
<x-dynamic-component :component="$componentName" :data="$data" />

<!-- Example -->
@php
    $componentName = 'alert';
    $data = ['type' => 'error', 'message' => 'Error!'];
@endphp

<x-dynamic-component :component="$componentName" :type="$data['type']" :message="$data['message']" />

Dynamic component selection بر اساس variable.

موارد استفاده

  • ایجاد reusable UI elements
  • سازمان‌دهی view code
  • ایجاد design system components
  • کاهش code duplication
  • مدیریت complex UI logic
  • ایجاد component library

اشتباهات رایج

  • استفاده از class-based component برای simple components
  • عدم استفاده از props که باعث hard-coding می‌شود
  • فراموش کردن attributes merging
  • قرار دادن business logic در component
  • عدم استفاده از slots برای flexibility
  • Component namespaces که باعث confusion می‌شود

بهترین روش‌ها

  • از anonymous components برای simple components استفاده کنید
  • از class-based components برای complex logic استفاده کنید
  • از props برای data passing استفاده کنید
  • از slots برای dynamic content استفاده کنید
  • از attributes merging برای HTML attributes استفاده کنید
  • Component names را descriptive انتخاب کنید
  • Components را test کنید

موارد خاص

  • Nested components با complex data flow
  • Components با conditional rendering
  • Dynamic component selection
  • Components با event handling
  • Component caching در production
  • Components با very large props

نکات عملکرد

  • Anonymous components سریع‌تر از class-based هستند
  • Component compilation cached می‌شود
  • استفاده از inline components می‌تواند overhead داشته باشد
  • Nested components می‌توانند slow باشند
  • Component caching در production بهبود performance می‌دهد

نکات امنیتی

  • مطمئن شوید که props به درستی escaped می‌شوند
  • از raw output در components با احتیاط استفاده کنید
  • مطمئن شوید که user input در props validated می‌شود
  • از component namespaces برای isolation استفاده کنید

نکات مصاحبه

  • تفاوت بین anonymous و class-based component چیست؟
  • Props چیست و چگونه کار می‌کند؟
  • Slots چیست و چه زمانی استفاده می‌شود؟
  • Attributes merging چگونه کار می‌کند؟
  • چگونه می‌توان component namespace تعریف کرد؟
  • مزایای استفاده از Blade components چیست؟

یادداشت‌های نسخه

  • Laravel 11.x: بهبود performance در component rendering
  • Laravel 11.x: پشتیبانی بهتر از attributes merging
  • Laravel 10.x: بهبود anonymous components
  • Laravel 9.x: بهبود component namespaces