0Pricing
C# Academy · درس

نموذج مكوّنات Blazor

أنشئوا مكوّنات Razor، وافهموا دورة حياة المكوّن، واستخدموا المعلمات والقيم المتسلسلة.

نموذج مكوّنات Blazor درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.

ما هو Blazor؟

يتيح لكم Blazor إنشاء واجهات ويب تفاعلية باستخدام C# بدلًا من JavaScript. وتُعرّف المكونات في ملفات .razor التي تجمع بين ترميز HTML ومنطق C#. ويعمل Blazor على الخادم (Blazor Server) أو في المتصفح عبر WebAssembly (Blazor WASM).

مكوّنك الأول

مكوّن Razor هو ملف .razor يتضمن ترميز HTML وكتلة @code للغة C#. ويصبح اسم المكوّن اسم وسم HTML.

@* Greeting.razor *@
<h2>Hello, @Name!</h2>
<p>You have @Count messages.</p>

@code {
    [Parameter] public string Name { get; set; } = "World";
    private int Count = 5;
}

دورة حياة المكوّن

تملك مكونات Blazor دورة حياة تتضمن نقاط ربط يمكنكم تجاوزها. وأكثرها شيوعًا OnInitializedAsync (تحميل البيانات) وOnParametersSetAsync (التفاعل مع تغييرات المعلمات).

@code {
    private List<Product> Products = new();

    protected override async Task OnInitializedAsync()
    {
        // Called once on first render
        Products = await Http.GetFromJsonAsync<List<Product>>("/api/products")
                   ?? new();
    }

    protected override async Task OnParametersSetAsync()
    {
        // Called whenever parameters change
        await LoadDataAsync();
    }
}

المعلمات: تمرير البيانات إلى المكونات

زيّنوا الخصائص باستخدام [Parameter] لقبول البيانات من المكونات الأصلية. وتُضبط المعلمات قبل العرض، ويمكن أن تؤدي تغييراتها إلى إعادة العرض.

@* ProductCard.razor *@
<div class="card">
    <h4>@Product.Name</h4>
    <p>Price: @Product.Price.ToString("C")</p>
    <button @onclick="AddToCart">Add to Cart</button>
</div>

@code {
    [Parameter, EditorRequired]
    public Product Product { get; set; } = default!;

    [Parameter]
    public EventCallback<Product> OnAddToCart { get; set; }

    private async Task AddToCart() =>
        await OnAddToCart.InvokeAsync(Product);
}

المعلمات المتسلسلة

تنتقل المعلمات المتسلسلة إلى أسفل شجرة المكونات من دون تمرير صريح عبر كل مستوى وسيط — ما يجعلها مثالية للسمات أو معلومات المستخدم أو الحالة المشتركة.

@* App.razor — wraps the whole app *@
<CascadingValue Value="CurrentUser">
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" DefaultLayout="@typeof(MainLayout)" />
        </Found>
    </Router>
</CascadingValue>

@* Anywhere in the tree: *@
@code {
    [CascadingParameter]
    public UserInfo CurrentUser { get; set; } = default!;
}

عرض القوائم والشروط

استخدموا توجيهات Razor ‏@if و@foreach و@for لعرض محتوى ديناميكي. واحرصوا دائمًا على توفير @key لعناصر القوائم لإجراء المقارنة بكفاءة.

@if (Products.Count == 0)
{
    <p>No products found.</p>
}
else
{
    <ul>
        @foreach (var product in Products)
        {
            <li @key="product.Id">
                <ProductCard Product="product" OnAddToCart="HandleAdd" />
            </li>
        }
    </ul>
}

RenderFragment وChildContent

استخدموا RenderFragment لتمرير الترميز بوصفه معلمة — مثل الفتحات في Vue أو العناصر الفرعية في React. واسم المعلمة المتعارف عليه هو ChildContent.

@* Panel.razor *@
<div class="panel">
    <div class="panel-header">@Title</div>
    <div class="panel-body">@ChildContent</div>
</div>

@code {
    [Parameter] public string Title { get; set; } = "";
    [Parameter] public RenderFragment? ChildContent { get; set; }
}

@* Usage: *@
<Panel Title="Order Details">
    <p>Order #42 — Shipped</p>
</Panel>

مراجع المكونات باستخدام @ref

التقطوا مرجعًا إلى مكوّن فرعي باستخدام @ref لاستدعاء أساليبه العامة أو قراءة خصائصه من المكوّن الأصلي.

@* Parent.razor *@
<ConfirmDialog @ref="_dialog" OnConfirm="DeleteOrder" />
<button @onclick="() => _dialog!.Show()">Delete Order</button>

@code {
    private ConfirmDialog? _dialog;

    private async Task DeleteOrder()
    {
        await OrderService.DeleteAsync(CurrentOrderId);
        // Refresh UI...
    }
}

StateHasChanged وإعادة العرض اليدوية

يعيد Blazor العرض تلقائيًا بعد معالجات الأحداث. أما تغييرات الحالة غير المتزامنة خارج معالجات الأحداث (مثلًا، من مؤقت يعمل في الخلفية)، فتتطلب استدعاء StateHasChanged() يدويًا.

@implements IDisposable

<p>Time: @CurrentTime</p>

@code {
    private string CurrentTime = "";
    private Timer? _timer;

    protected override void OnInitialized()
    {
        _timer = new Timer(_ =>
        {
            CurrentTime = DateTime.Now.ToString("HH:mm:ss");
            InvokeAsync(StateHasChanged); // thread-safe re-render
        }, null, 0, 1000);
    }

    public void Dispose() => _timer?.Dispose();
}

ShouldRender لتحسين الأداء

تجاوزوا ShouldRender() لتخطي عمليات إعادة العرض غير الضرورية. وأعيدوا false عندما لا يتغير ناتج المكوّن، مما يقلل الحمل الناتج عن المقارنة.

@code {
    private string _lastRenderedStatus = "";

    [Parameter] public string Status { get; set; } = "";

    protected override bool ShouldRender()
    {
        // Only re-render if Status actually changed
        if (Status == _lastRenderedStatus) return false;
        _lastRenderedStatus = Status;
        return true;
    }
}

من الواقع العملي: مكوّن قائمة المنتجات

مكوّن كامل لقائمة المنتجات يحمّل البيانات عند التهيئة، ويتعامل مع حالة التحميل، ويمرر الأحداث إلى المكوّن الأصلي.

@inject HttpClient Http

@if (_loading)
{
    <p>Loading products...</p>
}
else
{
    @foreach (var p in _products)
    {
        <ProductCard Product="p" OnAddToCart="AddToCart" />
    }
}

@code {
    private List<Product> _products = new();
    private bool _loading = true;

    [Parameter] public EventCallback<Product> OnCartUpdated { get; set; }

    protected override async Task OnInitializedAsync()
    {
        _products = await Http.GetFromJsonAsync<List<Product>>("/api/products")
                   ?? new();
        _loading = false;
    }

    private async Task AddToCart(Product p) => await OnCartUpdated.InvokeAsync(p);
}

تحقق سريع

ما أسلوب دورة الحياة الأنسب لتحميل البيانات من واجهة API عند تهيئة مكوّن Blazor؟

مراجعة: نموذج مكونات Blazor

أهم النقاط:

  • تجمع ملفات .razor بين ترميز HTML وC# في كتلة @code
  • تقبل [Parameter] البيانات من المكوّن الأصلي؛ ويمرر EventCallback الأحداث إلى الأعلى
  • تنقل CascadingParameter البيانات إلى الأسفل من دون تمرير الخصائص عبر المكونات الوسيطة
  • ينشئ RenderFragment/ChildContent مكونات قابلة للتركيب قائمة على الفتحات
  • يُستخدم OnInitializedAsync لتحميل البيانات الأولي؛ وStateHasChanged لإعادة العرض اليدوية
  • يتخطى ShouldRender() المقارنة غير الضرورية لتحسين الأداء

الأسئلة الشائعة

هل درس «نموذج مكوّنات Blazor» مجاني؟

نعم — نص درس «نموذج مكوّنات Blazor» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.

ماذا ستتعلم في «نموذج مكوّنات Blazor»؟

أنشئوا مكوّنات Razor، وافهموا دورة حياة المكوّن، واستخدموا المعلمات والقيم المتسلسلة. تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟

لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «نموذج مكوّنات Blazor»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟

نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. نموذج مكوّنات Blazor
  2. ربط البيانات ومعالجة الأحداث
  3. التواصل بين المكوّنات وDI
  4. إدارة الحالة في Blazor
← العودة إلى C# Academy