Hallo Habr!
Also ja, Net Core 3.0 kommt bald und es wird eine Projektvorlage mit Blazor als einer der Standardvorlagen geben. Der Name des Frameworks ähnelt meiner Meinung nach dem Namen einiger Pokémon. Blazor tritt in die Schlacht ein! Ich beschloss zu schauen, was für ein Tier es ist und womit es gegessen wird, also machte ich ein Todo-Blatt darauf. Nun, auch auf Vue.js zum Vergleich mit dem Thema, weil sie meiner Meinung nach sowohl in Bezug auf die Reaktivität als auch in Bezug auf die Reaktivität dem Komponentensystem ähnlich sind, und das ist alles. Mehr Göttinnen Gott Götter! Tatsächlich ist dies ein Leitfaden für junge, nicht starke Köpfe, die zu faul sind, um TypeScript oder JavaScript zu lernen, und Schaltflächen und Eingaben auf der Website vornehmen möchten. Wie in diesem Mem - "Der Technikfreak wollte ein Buch schreiben, aber die Anweisung stellte sich heraus." Wer interessiert sich für meine Abenteuer im Frontend oder findet heraus, welche Art von Blazor du bei Katze willkommen bist.
Einführung
Microsoft hatte einmal die Idee, C # in einem Browser zu arbeiten, und nannte diese Idee Silverlight. Es ist nicht gestartet. Diese Ihre Tyrnets waren dann anders als eigentlich Browser. Warum denke ich, dass es jetzt abhebt? Denn jetzt sind Web-Assemblys standardmäßig in allen modernen Browsern vorhanden. Es ist nicht erforderlich, eine separate Erweiterung zu installieren. Ein weiteres Problem sind die Anwendungsgrößen. Wenn Vue.js SPA 1,7 Megabyte wiegt, ist dies bei Blazor 21 Megabyte genau dasselbe. Jetzt ist das Internet schneller und zuverlässiger als während Silverlight und Sie müssen die Anwendung einmal herunterladen, und dann gibt es den Cache und die ganze Arbeit. Im Allgemeinen schien Blazor Vue.js sehr ähnlich zu sein. Als Hommage an Silverligtht, WPF und UWP und nur weil es unter Schärfern so häufig war, entschied ich mich, das MVVM-Muster für mein Projekt zu verwenden. Also als Referenz - ich bin im Allgemeinen ein Back-End und ich mochte Blazor. Ich warne schwache Nerven - Das Design und Layout in meinen Beispielen ist schrecklich, und im Projekt mit Vue.js kann ein erfahrener Front-End-Autor viel Govnokod sehen. Nun, mit Rechtschreibung und Zeichensetzung sind die Dinge auch so lala.
Referenzen
Todo Beispiel auf Vue + VuexTodo Beispiel auf BlazorPlatzierungsmodelle
- Auf der Client-Seite. Ein Standard-SPA, das auf verschiedene Arten verteilt werden kann. In meinem Beispiel habe ich eine Vorlage verwendet, in der die Anwendungsdateien an den Browserserver auf asp.net core gesendet werden. Der Nachteil dieses Ansatzes liegt in den 21 Megabyte, die Sie in den Browser herunterladen müssen.
- Auf der Serverseite. Alles geschieht auf dem Server, und das fertige DOM wird über Sockets an den Client übergeben. Der Browser muss zu Beginn überhaupt nichts herunterladen, sondern lädt das aktualisierte DOM ständig in Teilen herunter. Nun, die gesamte Last des Client-Codes fällt plötzlich auf den Server.
Ich persönlich mag die erste Option mehr und kann in all den Fällen verwendet werden, in denen Sie sich nicht um Benutzerkonvertierungen kümmern müssen. Dies ist beispielsweise eine Art internes Informationssystem des Unternehmens oder eine spezialisierte B2B-Lösung, da Blazor zum ersten Mal seit langer Zeit heruntergeladen hat. Wenn sich Ihre Benutzer ständig bei Ihrer Anwendung anmelden, werden sie keinen Unterschied zur JS-Version feststellen. Wenn ein Benutzer auf einen Werbelink klickt, schauen Sie sich einfach an, welche Art von Website vorhanden ist. Wahrscheinlich wird er nicht lange auf das Laden der Website warten und diese einfach verlassen. In diesem Fall ist es besser, die zweite Platzierungsoption zu verwenden, d.h. Server Side Blazor
Projekterstellung
Laden Sie net core 3.0
dotnet.microsoft.com/download/dotnet-core/3.0 herunterFühren Sie den Befehl im Terminal aus, der die erforderlichen Vorlagen für Sie lädt.
dotnet new -i Microsoft.AspNetCore.Blazor.Templates
So erstellen Sie eine Serverseite
dotnet new blazorserverside -o MyWebApp
Für die Client-Seite, deren Dateien vom asp.net-Kernserver verteilt werden
dotnet new blazorhosted -o MyWebApp
Wenn Sie Exotik wollten und sich plötzlich entschieden haben, den asp.net-Kern nicht als Server zu verwenden, sondern etwas anderes (Benötigen Sie ihn überhaupt?) Mit diesem Befehl können Sie nur einen Client ohne Server erstellen.
dotnet new blazor -o MyWebApp
Bindungen
Unterstützt Einweg- und Zweiwegbindung. Also ja, Sie brauchen kein OnPropertichanged wie in WPF. Beim Ändern des Ansichtsmodells ändert sich das Layout automatisch.
<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" />
Und so haben wir hier ein ViewModel (anonym), das ein Textfeld hat.
Bei der ersten Eingabe haben wir über "value = @ Text" eine Einwegbindung vorgenommen. Wenn wir nun den Text im Code ändern, ändert sich der Text in der Eingabe sofort. Nur damit wir unsere Eingaben nicht drucken, wirkt sich dies in keiner Weise auf unsere VM aus. In der zweiten Eingabe haben wir über "@ bind = @ Text" eine bidirektionale Bindung durchgeführt. Wenn wir nun etwas Neues in unsere Eingabe schreiben, ändert sich unsere VM sofort, und das Gegenteil ist auch der Fall, d. H. Wenn wir das Textfeld im Code ändern, zeigt unsere Eingabe sofort den neuen Wert an. Es gibt einen ABER - standardmäßig sind die Änderungen an das Ereignis onchange unserer Eingabe gebunden, sodass sich die VM erst ändert, wenn wir die Eingabe beendet haben. In der dritten Eingabe "@bind: event =" oninput "" haben wir das Ereignis für die Übertragung von VM-Daten in oninput geändert. Jedes Mal, wenn wir ein Zeichen drucken, wird sofort ein neuer Wert an unsere VM übertragen. Sie können beispielsweise auch ein Format für DateTime angeben.
<input @bind=@Today @bind:format="yyyy-MM-dd" />
Modell anzeigen
Sie können es anonymisieren, dann müssen Sie es im Block "@code {}" stoppen.
@page "/todo" <p> @UserName </p> @code{ public string UserName{get; set;} }
oder Sie können es in einer separaten Datei ablegen. Dann muss es von ComponentBase geerbt werden und oben auf der Seite einen Link zu unserer VM mit "@inherits" angeben.
Zum Beispiel
TodoViewModel.cs:
public class TodoViewModel: ComponentBase{ public string UserName{get; set;} }
Todo.razor:
@page "/todo" @inherits MyWebApp.ViewModels.TodoViewModel <p> @UserName </p>
Routing
Die Routen, auf die die Seite reagiert, werden am Anfang der Seite mit "@page" angegeben. Darüber hinaus kann es mehrere geben. Der erste wird genau passend in der Reihenfolge von oben nach unten ausgewählt. Zum Beispiel:
@page "/todo" @page "/todo/delete" <h1> Hello!</h1>
Diese Seite wird unter "/ todo" oder "todo / delete" geöffnet.
Layouts
Im Allgemeinen werden hier Dinge platziert, die für mehrere Seiten gleich sind. Wie eine Seitenleiste und mehr.
Um das Layout überhaupt verwenden zu können, müssen Sie es erstellen. Es muss mit "@inherits" von LayotComponentBase geerbt werden. Zum Beispiel
@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>
Zweitens muss es importiert werden. Dazu müssen Sie in dem Verzeichnis mit den Seiten, auf denen es verwendet wird, die Datei _imports.razor erstellen und dieser Datei die Zeile "@layout" hinzufügen
@layout MainLayout @using System
Drittens können Sie auf der Seite angeben, welches Layout direkt verwendet wird
@layout MainLayout @page "/todo" @inherits BlazorApp.Client.Presentation.TodoViewModel <h3>Todo</h3>
Im Allgemeinen wirken _imports.razor und die Verwendung darin auf alle Seiten, die sich im selben Ordner befinden.
Routenoptionen
Geben Sie zunächst den Parameter und seinen Typ in geschweiften Klammern in unserer Route an (Groß- und Kleinschreibung wird nicht berücksichtigt). Standardtypen werden unterstützt. Also ja, es gibt keine optionalen Parameter, d.h. Wert muss immer übergeben werden.
Der Wert selbst kann erhalten werden, indem in unserem ViewModel eine Eigenschaft mit demselben Namen wie der Parameter und mit dem zuvor ausgeführten BTB-Attribut [Parameter] erstellt wird. Die Daten und Ereignisse in den übergeordneten Komponenten werden auch von den übergeordneten Komponenten mithilfe des Attributs [Parameter] sowie über kaskadierende Parameter übertragen. Sie werden von der übergeordneten Komponente an alle untergeordneten Komponenten und deren untergeordnete Komponenten übergeben. Sie werden hauptsächlich für Stile verwendet, aber es ist besser, nur Stile in CSS zu erstellen. Warum also nicht?
@page "/todo/delete/{id:guid}" <h1> Hello!</h1> @code{ [Parameter] public Guid Id { get; set; } }
DI
Alles ist in Startup.cs registriert, wie in einer regulären asp.net-Kernanwendung. Hier gibt es nichts Neues. Die Implementierung von Abhängigkeiten für unsere VM erfolgt jedoch weiterhin über öffentliche Eigenschaften und nicht über den Konstruktor. Die Eigenschaft muss nur mit dem Attribut [Inject] dekoriert werden
public class DeleteTodoViewModel : ComponentBase { [Parameter] private Guid Id { get; set; } [Inject] public ICommandDispatcher CommandDispatcher { get; set; }
Standardmäßig sind bereits 3 Dienste verbunden. HttpClient - Nun, Sie wissen warum. IJSRuntime - JS-Code von C # aufrufen. IUriHelper - Mit dieser Funktion kann nicht auf andere Seiten umgeleitet werden.
Anwendungsbeispiel
Todo Tabellenkalkulation
TodoTableComponent.razor:
- Da diese Komponente "@page" und "@layout" nicht benötigt, nimmt sie nicht am Routing teil und verwendet das Layout der übergeordneten Komponente
- Der C # -Code beginnt mit dem @ -Symbol. Eigentlich das gleiche wie bei Razor
@onclick=@(()=>ClickRow(item.Id))
Bindet ein Zeilenklickereignis an die ClickRow-Methode unseres ViewModel- Geben Sie mit dem Attribut [Parameter] an, welche Parameter von der übergeordneten Komponente oder Seite zu unserer übertragen werden
- Wir rufen die Rückruffunktion auf, die von der übergeordneten Komponente empfangen wurde. Die übergeordnete Komponente erfährt also, dass im untergeordneten Element ein Ereignis aufgetreten ist. Funktionen können nur in EventCallback <> parametrisierten EventArgs verpackt übergeben werden. Eine mögliche Liste von EventArgs finden Sie hier - docs.microsoft.com/ru-ru/aspnet/core/blazor/components?view=aspnetcore-3.0#event-handling
- Da die Liste der möglichen Arten von EventArgs begrenzt ist und wir eine zusätzliche Id-Eigenschaft an den Ereignishandler auf der Seite der übergeordneten Komponente übergeben müssen, erstellen wir unsere eigene Parameterklasse, die von der Basis geerbt wurde, und übergeben sie an das Ereignis. Also ja - in der übergeordneten Komponente fliegen die regulären UIMouseEventArgs in die Funktion des Ereignishandlers und müssen beispielsweise mit dem Operator as in unseren Typ konvertiert werden
Anwendungsbeispiel:
<TodoTableComponent Items=@Items OnClick=@Select Current=@(Selected?.Id??Guid.Empty)></TodoTableComponent>
Todo Entfernungsseite
Unser ViewModel aka VM ist DeleteTodoViewModel.cs:
public class DeleteTodoViewModel : ComponentBase {
- Der Routenparameter "/ todo / delete / {id: guid}" wird hier an Guid übergeben, wenn wir beispielsweise an localhost / todo / delete / ae434aae44 gehen ...
- Injizieren Sie Services aus dem DI-Container in unsere VM.
- Nur eine Eigenschaft unserer VM. Wir setzen seinen Wert selbst, wie wir wollen.
- Diese Methode wird automatisch aufgerufen, wenn die Seite initialisiert wird. Hier legen wir die notwendigen Werte für die Eigenschaften unserer VM fest
- Die Methode unserer VM. Wir können es zum Beispiel an den Fall binden, dass wir auf eine beliebige Schaltfläche in unserer Ansicht klicken
- Gehen Sie zu einer anderen Seite unter der Adresse "/ todo", dh sie hat am anfang die zeile "@page" / todo ""
Unsere Ansicht ist DeleteTodo.razor:
- Wir geben an, dass dieses Land unter der Adresse {Stammadresse unserer Website} + "/ todo / delete /" + {eine Art Guid} verfügbar sein wird. Zum Beispiel localhost / todo / delete / ae434aae44 ...
- Geben Sie an, dass unsere Seite in MainLayout.razor gerendert wird
- Geben Sie an, dass unsere Seite die Eigenschaften und Methoden der DeleteTodoViewModel-Klasse verwendet
- Wenn Sie auf diese Schaltfläche klicken, wird die Delete () -Methode unserer VM aufgerufen
Todo nach Hause
TodoViewModel.cs:
public class TodoViewModel : ComponentBase { [Inject] public ICommandDispatcher CommandDispatcher { get; set; } [Inject] public IQueryDispatcher QueryDispatcher { get; set; }
- Die Standardvalidierungsattribute von System.ComponentModel.DataAnnotations werden unterstützt. Insbesondere geben wir hier an, dass dieses Feld erforderlich ist und der Text, der angezeigt wird, wenn der Benutzer keinen Wert in der Eingabe angibt, der diesem Feld zugeordnet wird.
- Methode zur Behandlung eines Ereignisses mit einem Parameter. Diese Methode behandelt das Ereignis von der untergeordneten Komponente.
- Wir wandeln das Argument in den Typ um, den wir in der untergeordneten Komponente erstellt haben
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 {
- Wir rufen die untergeordnete Komponente auf und übergeben ihr die Eigenschaften und Methoden unserer VM als Parameter.
- Integrierte Formularkomponente mit Datenvalidierung. Wir geben darin an, dass er als Modell unsere VM verwenden und beim Senden gültiger Daten die Create () -Methode aufrufen wird
- Die Validierung wird anhand von Modellattributen wie [Erforderlich] usw. durchgeführt.
- Hier werde ich die allgemeinen Validierungsfehler anzeigen
- Erstellt eine Eingabe mit Validierung. Die Liste der möglichen Tags lautet InputText, InputTextArea, InputSelect, InputNumber, InputCheckbox, InputDate
- Hier werden Validierungsfehler für die öffentliche Zeichenfolgeeigenschaft NewTodo {get; set;} angezeigt
- Wenn Sie auf diese Schaltfläche klicken, wird das OnValidSubmit-Ereignis unseres Formulars ausgelöst
Datei Startup.cs
Hier registrieren wir unsere Dienste
public class Startup { public void ConfigureServices(IServiceCollection services) {
Nachwort
Dieser Artikel wurde geschrieben, um Appetit zu machen und das weitere Studium von Blazor zu fördern. Ich hoffe, dass ich mein Ziel erreicht habe. Um es besser zu studieren, empfehle ich, das offizielle Handbuch von Microsoft zu lesen.
Danksagung
Vielen Dank an AndreyNikolin , win32nipuh , SemenPV für die gefundenen Rechtschreib- und Grammatikfehler im Text.