مرحبا يا هبر!
إذن ، نعم ، سيتم طرح net core 3.0 قريبًا وسيكون هناك قالب مشروع مع Blazor كواحد من القوالب الافتراضية. اسم الإطار ، في رأيي ، يشبه اسم بعض بوكيمون. Blazor يدخل المعركة! قررت أن ننظر إلى أي نوع من الحيوانات هو وماذا يؤكل معها ، لذلك صنعت ورقة تودو عليها. حسنًا ، على Vue.js أيضًا ، للمقارنة مع الموضوع لأنهم في رأيي يشبهون نظام المكونات في كل من التفاعلية ، وهذا كل شيء. المزيد من الآلهة آلهة الله! في الواقع ، يعد هذا دليلًا لعقول الشباب ، وليس الأقوياء الذين هم كسولون جدًا لتعلم TypeScript أو JavaScript ويريدون إنشاء أزرار ومدخلات على الموقع. كما في تلك الميم - "أراد الفني أن يكتب كتابًا ولكن التعليمات انتهت". من يهتم بمغامراتي في الواجهة الأمامية أو اكتشف نوع Blazor الذي نرحب به في القط.
مقدمة
كانت لدى Microsoft فكرة العمل على C # في أحد المستعرضات وتسمى هذه الفكرة Silverlight. لم تقلع وكانت هذه tynets الخاص بك ثم مختلفة مثل المتصفحات في الواقع. لماذا أعتقد أن هذا بدأ الآن؟ نظرًا لأن تجميعات الويب الآن موجودة في جميع المتصفحات الحديثة افتراضيًا. ليست هناك حاجة لتثبيت ملحق منفصل. قضية أخرى هي أحجام التطبيق. إذا كان Vue.js SPA يزن 1.7 ميجابايت ، فستكون بالضبط نفس القيمة على Blazor 21 ميغابايت. أصبح الإنترنت الآن أسرع وأكثر موثوقية مما كان عليه أثناء Silverlight وتحتاج إلى تنزيل التطبيق مرة واحدة ، ثم توجد ذاكرة التخزين المؤقت وكل العمل. بشكل عام ، بدا Blazor مشابهًا جدًا لـ Vue.js. وهكذا ، كتقدير لـ Silverligtht و WPF و UWP ، ولأنه كان شائعًا جدًا بين الأدوات الحادة ، فقد قررت استخدام نمط MVVM لمشروعي. كمرجع - أنا عادةً خلفية - وأعجبني Blazor. أحذر من ضعف القلب - التصميم والتصميم في الأمثلة الخاصة بي فظيعان ، وفي المشروع مع Vue.js يمكن للكاتب الأمامي ذي الخبرة رؤية الكثير من govnokod. حسنًا ، مع التهجئة وعلامات الترقيم ، فإن الأمور كذلك.
مراجع
مثال تودو على Vue + Vuexمثال تودو على بليزورنماذج المواضع
- على جانب العميل. منتجع صحي قياسي يمكن توزيعه بعدة طرق. في المثال الخاص بي ، استخدمت قالبًا يتم إرسال ملفات التطبيقات فيه إلى خادم المتصفح على asp.net core. عيب هذا النهج هو في تلك 21 ميغابايت التي تحتاج إلى تحميلها إلى المتصفح.
- على جانب الخادم. كل شيء يحدث على الخادم ، ويتم تمرير DOM النهائي إلى العميل من خلال مآخذ. لا يحتاج المتصفح إلى تنزيل أي شيء على الإطلاق في البداية ، ولكن بدلاً من ذلك يقوم باستمرار بتنزيل DOM المحدث على شكل أجزاء. حسنا ، الحمل بأكمله على رمز العميل يقع فجأة على الخادم.
أنا شخصياً أحب الخيار الأول أكثر ، ويمكن استخدامه في جميع تلك الحالات عندما لا تكون بحاجة للقلق بشأن تحويلات المستخدمين. على سبيل المثال ، هذا نوع من نظام المعلومات الداخلي للشركة أو حل B2B متخصص لأن Blazor تم تنزيله لفترة طويلة للمرة الأولى. إذا قام المستخدمون بتسجيل الدخول باستمرار إلى التطبيق الخاص بك ، فلن يلاحظوا أي فرق مع إصدار JS. إذا نقر أحد المستخدمين على رابط الإعلان ، فما عليك سوى إلقاء نظرة على نوع الموقع الموجود ، وعلى الأرجح لن ينتظر طويلًا حتى يتم تحميل الموقع ويترك فقط. في هذه الحالة ، من الأفضل استخدام خيار الموضع الثاني ، أي خادم الجانب السترة
إنشاء المشروع
قم بتنزيل net core 3.0
dotnet.microsoft.com/download/dotnet-core/3.0قم بتشغيل الأمر في الجهاز الذي سيقوم بتحميل القوالب اللازمة لك.
dotnet new -i Microsoft.AspNetCore.Blazor.Templates
لإنشاء جانب الخادم
dotnet new blazorserverside -o MyWebApp
بالنسبة إلى جانب العميل الذي سيتم توزيع ملفاته بواسطة خادم asp.net الأساسي
dotnet new blazorhosted -o MyWebApp
إذا أردت الغريبة وقررت فجأة عدم استخدام asp.net الأساسية كخادم ، ولكن شيئا آخر (هل تحتاج إليها على الإطلاق؟) يمكنك إنشاء عميل فقط دون خادم مع هذا الأمر.
dotnet new blazor -o MyWebApp
الارتباطات
يدعم أحادي الاتجاه وثنائي الاتجاه. نعم ، أنت لا تحتاج إلى أي OnPropertichanged كما في WPF. عند تغيير "نموذج العرض" ، يتغير التخطيط تلقائيًا.
<label>One way binding:</label> <br /> <input type="text" value=@Text /> <br /> <label>Two way binding:</label> <br /> <input type="text" @bind=@Text /> <br /> <label>Two way binding Text oninput:</label> <br /> <input type="text" @bind=@Text @bind:event="oninput" />
وهكذا ، لدينا هنا ViewModel (مجهول) يحتوي على حقل نص.
في الإدخال الأول ، من خلال "value = @ Text" ، جعلنا الربط أحادي الاتجاه. الآن عندما نغير النص في الكود ، فإن النص الموجود داخل الإدخال سيتغير على الفور. فقط بحيث لا نقوم بطباعة المدخلات الخاصة بنا يؤثر هذا بأي طريقة على VM الخاص بنا. في الإدخال الثاني ، من خلال "@ bind = @ Text" ، جعلنا الربط ثنائي الاتجاه. الآن إذا كتبنا شيئًا جديدًا في مدخلاتنا ، فسوف يتغير جهاز VM لدينا على الفور ، والعكس صحيح أيضًا أي إذا قمنا بتغيير حقل النص في الكود ، فسيعرض مدخلاتنا على الفور القيمة الجديدة. هناك BUT واحد - افتراضيًا ، ترتبط التغييرات بحدث onchange لمدخلاتنا ، لذلك لن يتغير VM إلا عند الانتهاء من الإدخال. في الإدخال الثالث "bind: event =" oninput "" قمنا بتغيير الحدث الخاص بنقل بيانات VM إلى oninput الآن في كل مرة نطبع فيها بعض الأحرف ، يتم نقل قيمة جديدة على الفور إلى VM الخاص بنا. يمكنك أيضًا تحديد تنسيق لـ DateTime ، على سبيل المثال ، مثل هذا.
<input @bind=@Today @bind:format="yyyy-MM-dd" />
عرض النموذج
يمكنك جعله مجهولًا ثم تحتاج إلى إيقافه داخل الكتلة "code {}"
@page "/todo" <p> @UserName </p> @code{ public string UserName{get; set;} }
أو يمكنك وضعها في ملف منفصل. بعد ذلك ، يجب أن يتم توريثه من ComponentBase وفي الجزء العلوي من الصفحة ، حدد رابطًا إلى VM باستخدام "inherits"
على سبيل المثال
TodoViewModel.cs:
public class TodoViewModel: ComponentBase{ public string UserName{get; set;} }
Todo.razor:
@page "/todo" @inherits MyWebApp.ViewModels.TodoViewModel <p> @UserName </p>
التوجيه
تتم الإشارة إلى الطرق التي سترد عليها الصفحة في بداية الصفحة باستخدام "@ page". علاوة على ذلك ، قد يكون هناك عدة. سيتم اختيار أول واحد مطابق تمامًا بالترتيب من الأعلى إلى الأسفل. على سبيل المثال:
@page "/todo" @page "/todo/delete" <h1> Hello!</h1>
سيتم فتح هذه الصفحة في "/ todo" أو "todo / delete"
Layauty
بشكل عام ، عادة ما يتم وضع الأشياء التي تتشابه في عدة صفحات هنا. مثل الشريط الجانبي ، وأكثر من ذلك.
من أجل استخدام التخطيط في المقام الأول ، تحتاج إلى إنشائه. يجب أن تكون موروثة من LayotComponentBase باستخدام "inherits". على سبيل المثال
@inherits LayoutComponentBase <div class="sidebar"> <NavMenu /> </div> <div class="main"> <div class="top-row px-4"> <a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a> </div> <div class="content px-4"> @Body </div> </div>
ثانياً ، يجب استيرادها. للقيام بذلك ، في الدليل الذي يحتوي على الصفحات التي ستستخدمه ، ستحتاج إلى إنشاء ملف _imports.razor ثم إضافة السطر "layout" إلى هذا الملف
@layout MainLayout @using System
ثالثًا ، يمكنك الإشارة في الصفحة إلى التنسيق الذي يستخدمه مباشرةً
@layout MainLayout @page "/todo" @inherits BlazorApp.Client.Presentation.TodoViewModel <h3>Todo</h3>
بشكل عام ، يعمل _imports.razor واستخدامه في جميع الصفحات الموجودة في نفس المجلد معها.
خيارات الطريق
أولاً ، أشر إلى المعلمة ونوعها بين قوسين مجعدين في طريقنا (غير حساس لحالة الأحرف). أنواع قياسية معتمدة. إذن ، نعم ، لا توجد معايير اختيارية ، على سبيل المثال يجب دائمًا تمرير القيمة.
يمكن الحصول على القيمة نفسها من خلال إنشاء خاصية في ViewModel بنفس اسم المعلمة وبواسطة BTV [Parameter] - التي تعمل من قبل - يتم أيضًا نقل البيانات والأحداث في المكونات الأصلية باستخدام السمة [Parameter] كمعلمات متتالية. يتم تمريرها من المكون الأصل إلى جميع مكوناته الفرعية ومكوناتها الفرعية. يتم استخدامها بشكل أساسي للأنماط ، ولكن من الأفضل القيام فقط بالأنماط في CSS ، فلماذا لا تهتم.
@page "/todo/delete/{id:guid}" <h1> Hello!</h1> @code{ [Parameter] public Guid Id { get; set; } }
DI
كل شيء مسجل في Startup.cs ، كما هو الحال في تطبيق أساسي asp.net منتظم. لا جديد هنا لكن تنفيذ التبعيات الخاصة بـ VM لا يزال يحدث من خلال الخصائص العامة وليس من خلال المُنشئ. يجب أن يتم تزيين الخاصية فقط بسمة [Inject]
public class DeleteTodoViewModel : ComponentBase { [Parameter] private Guid Id { get; set; } [Inject] public ICommandDispatcher CommandDispatcher { get; set; }
بشكل افتراضي ، هناك 3 خدمات متصلة بالفعل. HttpClient - حسنًا ، أنت تعرف السبب. IJSRuntime - استدعاء رمز JS من C #. IUriHelper - باستخدامه ، لا يمكن إعادة التوجيه إلى صفحات أخرى.
مثال التطبيق
تودو جداول البيانات
TodoTableComponent.razor:
- نظرًا لأن هذا المكون لا نحتاج إلى "@ page" و "layout" لأنه لن يشارك في التوجيه وسيستخدم التنسيق من المكون الأصل
- يبدأ رمز C # بالرمز @. في الواقع نفسه كما هو الحال في الشفرة
@onclick=@(()=>ClickRow(item.Id))
يربط حدث نقر الصف بأسلوب ClickRow في ViewModel الخاص بنا- حدد المعلمات التي سيتم نقلها من المكون أو الصفحة الرئيسية إلى صفحتنا باستخدام السمة [Parameter]
- نحن ندعو وظيفة رد الاتصال التي تم تلقيها من المكون الأصل. لذلك يتعلم المكون الأصل أن حدثًا ما حدث في الطفل. لا يمكن تمرير الدالات إلا في EventCallback <> EventArgs ذات معلمات. يمكن العثور على قائمة ممكنة بـ EventArgs هنا - docs.microsoft.com/ru-ru/aspnet/core/blazor/components؟view=aspnetcore-3.0#event-handling
- نظرًا لأن قائمة الأنواع المحتملة من EventArgs محدودة ونحتاج إلى تمرير خاصية معرف إضافية إلى معالج الأحداث على جانب المكون الأصل ، فإننا ننشئ فئة المعلمة الخاصة بنا الموروثة من القاعدة ونمررها إلى الحدث. لذا نعم - في المكون الأصل ، ستنتقل UIMouseEventArgs العادية إلى وظيفة معالج الأحداث وستحتاج إلى تحويل إلى نوعنا ، على سبيل المثال ، باستخدام المشغل
مثال للاستخدام:
<TodoTableComponent Items=@Items OnClick=@Select Current=@(Selected?.Id??Guid.Empty)></TodoTableComponent>
تودو إزالة الصفحة
لدينا ViewModel الملقب VM هو DeleteTodoViewModel.cs:
public class DeleteTodoViewModel : ComponentBase {
- يتم تمرير معلمة المسار "/ todo / delete / {id: guid}" إلى Guid هنا إذا انتقلنا ، على سبيل المثال ، إلى المضيف المحلي / todo / delete / ae434aae44 ...
- ضخ الخدمات من حاوية DI في VM لدينا.
- مجرد خاصية لدينا VM. وضعنا قيمته بأنفسنا ، كما نريد.
- يتم استدعاء هذه الطريقة تلقائيًا عند تهيئة الصفحة. نحن هنا نضع القيم اللازمة لخصائص VM الخاصة بنا
- طريقة VM لدينا. يمكننا ربطه ، على سبيل المثال ، بحدث النقر على أي زر في طريقة العرض الخاصة بنا
- الذهاب إلى صفحة أخرى تقع على عنوان "/ ما يجب عمله" أي لديها في بداية السطر "@ page" / ما يجب عمله ""
وجهة نظرنا هي DeleteTodo.razor:
- نشير إلى أن هذا البلد سيكون متاحًا على العنوان {عنوان الجذر لموقعنا} + "/ todo / delete /" + {نوعًا ما من Guid}. على سبيل المثال localhost / todo / delete / ae434aae44 ...
- حدد أن صفحتنا سيتم عرضها داخل MainLayout.razor
- حدد أن صفحتنا سوف تستخدم الخصائص والأساليب لفئة DeleteTodoViewModel
- نقوم بتضييق ذلك عند النقر فوق هذا الزر ، سيتم استدعاء طريقة Delete () الخاصة بـ VM
تودو الرئيسية
TodoViewModel.cs:
public class TodoViewModel : ComponentBase { [Inject] public ICommandDispatcher CommandDispatcher { get; set; } [Inject] public IQueryDispatcher QueryDispatcher { get; set; }
- يتم دعم سمات التحقق من الصحة القياسية من System.ComponentModel.DataAnnotations. على وجه التحديد ، نشير هنا إلى أن هذا الحقل مطلوب والنص الذي سيتم عرضه إذا لم يحدد المستخدم قيمة في الإدخال الذي سيتم ربطه بهذا الحقل.
- طريقة للتعامل مع الحدث مع المعلمة. ستقوم هذه الطريقة بمعالجة الحدث من المكون الفرعي.
- نحن نوجه الوسيطة إلى النوع الذي أنشأناه في المكون الفرعي
Todo.razor:
@layout MainLayout @page "/todo" @inherits BlazorApp.Client.Presentation.TodoViewModel <h3>Todo</h3> <h4></h4> <div class="row"> <div class="col"> @if (Items == null) { <p><em>...</em></p> } else if (Items.Count == 0) { <p><em> . .</em></p> } else {
- نسمي المكون الفرعي ونمرر به خصائص وطرق VM الخاصة بنا كمعلمات.
- المدمج في مكون النموذج مع التحقق من صحة البيانات. نوضح في هذا النموذج أنه سيستخدم VM الخاص بنا ، وعند إرسال بيانات صالحة ، سيتصل بالطريقة Create () الخاصة به
- سيتم إجراء التحقق باستخدام سمات الطراز مثل [Requared] ، إلخ.
- هنا سأعرض الأخطاء العامة للتحقق من الصحة
- سيخلق المدخلات مع التحقق من الصحة. قائمة العلامات المحتملة هي InputText و InputTextArea و InputSelect و InputNumber و InputCheckbox و InputDate
- سيتم عرض أخطاء التحقق من الصحة لخاصية السلسلة العامة NewTodo {get؛ set؛} هنا
- عند النقر فوق هذا الزر ، سيتم رفع حدث OnValidSubmit الخاص بنا
ملف Startup.cs
هنا نسجل خدماتنا
public class Startup { public void ConfigureServices(IServiceCollection services) {
خاتمة
كتب هذا المقال للعب شهية وتشجيع مزيد من الدراسة من Blazor. آمل أن تكون قد حققت هدفي. حسنًا ، لدراسته بشكل أفضل ، أوصي بقراءة الدليل الرسمي من Microsoft .
شكر
بفضل AndreyNikolin ، win32nipuh ، SemenPV للأخطاء الإملائية والنحوية الموجودة في النص.