Bonjour, Habr!
Alors oui, net core 3.0 arrive bientôt et il y aura un modèle de projet avec Blazor comme l'un des modèles par défaut. Le nom du cadre, à mon avis, est similaire au nom de certains Pokémon. Blazor entre dans la bataille! J'ai décidé de regarder de quel type d'animal il s'agit et avec quoi il est mangé, alors j'ai fait une feuille Todo dessus. Eh bien, sur Vue.js aussi, pour la comparaison avec le sujet car à mon avis, ils sont similaires au système de composants en termes de réactivité, et c'est tout. Plus de dieux dieux dieux! En fait, c'est un guide pour les jeunes esprits, pas forts qui sont trop paresseux pour apprendre TypeScript ou JavaScript et qui veulent faire des boutons et des entrées sur le site. Comme dans ce meme - "Le technicien voulait écrire un livre mais l'instruction s'est avérée." Qui s'intéresse à mes aventures en front end ou qui découvre quel genre de Blazor vous êtes les bienvenus pour chat.
Présentation
Microsoft a eu l'idée de travailler en C # dans un navigateur et a appelé cette idée Silverlight. Ça n'a pas décollé. Ces tyrnets étaient alors différents comme des navigateurs. Pourquoi est-ce que je pense que ça décolle maintenant? Parce que maintenant les assemblys web sont par défaut dans tous les navigateurs modernes. Il n'est pas nécessaire d'installer une extension distincte. Un autre problème est la taille des applications. Si Vue.js SPA pèse 1,7 mégaoctets, alors exactement la même chose sur Blazor 21 mégaoctets. Maintenant, Internet est devenu plus rapide et plus fiable que pendant Silverlight et vous devez télécharger l'application une fois, puis il y a le cache et tout le travail. En général, Blazor semblait très similaire à Vue.js. Et donc, en hommage à Silverligtht, WPF et UWP, et juste parce qu'il était si courant chez les affûteurs, j'ai décidé d'utiliser le modèle MVVM pour mon projet. Donc pour référence - je suis généralement un back-end et j'ai aimé Blazor. Je préviens les âmes sensibles - La conception et la mise en page dans mes exemples sont terribles, et dans le projet avec Vue.js, un écrivain expérimenté peut voir beaucoup de govnokod. Eh bien, avec l'orthographe et la ponctuation, les choses sont aussi comme ça.
Les références
Exemple Todo sur Vue + VuexExemple de Todo sur BlazorModèles de placement
- Côté client. Un SPA standard qui peut être distribué de différentes manières. Dans mon exemple, j'ai utilisé un modèle dans lequel les fichiers d'application sont envoyés au serveur de navigateur sur le noyau asp.net. L'inconvénient de cette approche réside dans les 21 mégaoctets que vous devez télécharger sur le navigateur.
- Côté serveur. Tout se passe sur le serveur, et le DOM fini est transmis au client via des sockets. Le navigateur n'a pas besoin de télécharger quoi que ce soit au début, mais à la place, téléchargez constamment le DOM mis à jour en morceaux. Eh bien, la charge entière sur le code client tombe soudainement sur le serveur.
Personnellement, j'aime davantage la première option et je peux l'utiliser dans tous ces cas lorsque vous n'avez pas à vous soucier des conversions d'utilisateurs. Par exemple, il s'agit d'une sorte de système d'information interne de l'entreprise ou d'une solution B2B spécialisée car Blazor télécharge depuis longtemps pour la première fois. Si vos utilisateurs se connectent constamment à votre application, ils ne remarqueront aucune différence avec la version JS. Si un utilisateur clique sur un lien publicitaire, regardez simplement quel type de site est là, très probablement il n'attendra pas longtemps que le site se charge et quitte. Dans ce cas, il est préférable d'utiliser la deuxième option de placement, c'est-à-dire Blazor côté serveur
Création de projet
Télécharger net core 3.0
dotnet.microsoft.com/download/dotnet-core/3.0Exécutez la commande dans le terminal qui chargera les modèles nécessaires pour vous.
dotnet new -i Microsoft.AspNetCore.Blazor.Templates
Pour créer un côté serveur
dotnet new blazorserverside -o MyWebApp
Pour le côté client dont les fichiers seront distribués par le serveur principal asp.net
dotnet new blazorhosted -o MyWebApp
Si vous vouliez l'exotisme et avez soudainement décidé de ne pas utiliser le noyau asp.net comme serveur, mais autre chose (en avez-vous besoin?) Vous pouvez créer uniquement un client sans serveur avec cette commande.
dotnet new blazor -o MyWebApp
Liaisons
Prend en charge la liaison unidirectionnelle et bidirectionnelle. Donc oui, vous n'avez besoin d'aucun OnPropertichanged comme dans WPF. Lors de la modification du modèle de vue, la disposition change automatiquement.
<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" />
Et donc, nous avons ici un ViewModel (anonyme) qui a un champ Texte.
Dans la première entrée, via «value = @ Text», nous avons créé une liaison unidirectionnelle. Maintenant, lorsque nous modifions le texte dans le code, le texte à l'intérieur de l'entrée change immédiatement. Ce n'est que pour que nous n'imprimons pas dans notre entrée que cela affecte notre machine virtuelle. Dans la deuxième entrée, via "@ bind = @ Text", nous avons créé une liaison bidirectionnelle. Maintenant, si nous écrivons quelque chose de nouveau dans notre entrée, notre machine virtuelle changera immédiatement, et l'inverse est également vrai, c'est-à-dire si nous modifions le champ Texte dans le code, notre entrée affichera immédiatement la nouvelle valeur. Il y a un MAIS - par défaut, les changements sont liés à l'événement onchange de notre entrée, donc la VM ne changera que lorsque nous aurons terminé l'entrée. Dans la troisième entrée "@bind: event =" oninput "", nous avons changé l'événement pour le transfert des données VM en oninput maintenant chaque fois que nous imprimons un caractère, une nouvelle valeur est immédiatement transférée sur notre VM. Vous pouvez également spécifier un format pour DateTime, par exemple, comme ceci.
<input @bind=@Today @bind:format="yyyy-MM-dd" />
Voir le modèle
Vous pouvez le rendre anonyme, puis vous devez l'arrêter dans le bloc "@code {}"
@page "/todo" <p> @UserName </p> @code{ public string UserName{get; set;} }
ou vous pouvez le mettre dans un fichier séparé. Ensuite, il doit être hérité de ComponentBase et en haut de la page spécifier un lien vers notre VM en utilisant "@inherits"
Par exemple
TodoViewModel.cs:
public class TodoViewModel: ComponentBase{ public string UserName{get; set;} }
Todo.razor:
@page "/todo" @inherits MyWebApp.ViewModels.TodoViewModel <p> @UserName </p>
Acheminement
Les itinéraires auxquels la page répondra sont indiqués au début de la page en utilisant "@page". De plus, il peut y en avoir plusieurs. Le premier sera sélectionné exactement dans l'ordre de haut en bas. Par exemple:
@page "/todo" @page "/todo/delete" <h1> Hello!</h1>
Cette page s'ouvrira dans "/ todo" ou "todo / delete"
Disposition
En général, les éléments identiques pour plusieurs pages sont généralement placés ici. Comme une barre latérale, et plus encore.
Pour utiliser la mise en page en premier lieu, vous devez la créer. Il doit être hérité de LayotComponentBase en utilisant "@inherits". Par exemple
@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>
Deuxièmement, il doit être importé. Pour ce faire, dans le répertoire des pages qui vont l'utiliser, vous devez créer le fichier _imports.razor puis ajouter la ligne "@layout" à ce fichier
@layout MainLayout @using System
Troisièmement, vous pouvez indiquer sur la page quelle disposition il utilise directement
@layout MainLayout @page "/todo" @inherits BlazorApp.Client.Presentation.TodoViewModel <h3>Todo</h3>
En général, _imports.razor et son utilisation agissent sur toutes les pages qui se trouvent dans le même dossier que lui.
Options d'itinéraire
Tout d'abord, indiquez le paramètre et son type entre accolades dans notre itinéraire (insensible à la casse). Les types standard sont pris en charge. Alors oui, il n'y a pas de paramètres optionnels, c'est-à-dire la valeur doit toujours être transmise.
La valeur elle-même peut être obtenue en créant dans notre ViewModel une propriété avec le même nom que le paramètre et avec l'attribut BTV [Parameter] - en cours d'exécution avant - les données et les événements dans les composants parents sont également transmis en utilisant l'attribut [Parameter] comme paramètres en cascade. Ils sont passés du composant parent à tous ses composants enfants et à leurs composants enfants. Ils sont principalement utilisés pour les styles, mais il vaut mieux ne faire que des styles en CSS, alors pourquoi ne pas s'en soucier.
@page "/todo/delete/{id:guid}" <h1> Hello!</h1> @code{ [Parameter] public Guid Id { get; set; } }
DI
Tout est enregistré dans Startup.cs, comme dans une application principale asp.net standard. Rien de nouveau ici. Mais l'implémentation des dépendances pour notre machine virtuelle se fait toujours via les propriétés publiques et non via le constructeur. La propriété doit simplement être décorée avec l'attribut [Inject]
public class DeleteTodoViewModel : ComponentBase { [Parameter] private Guid Id { get; set; } [Inject] public ICommandDispatcher CommandDispatcher { get; set; }
Par défaut, 3 services sont déjà connectés. HttpClient - Eh bien, vous savez pourquoi. IJSRuntime - Appelle le code JS depuis C #. IUriHelper - en l'utilisant, il n'est pas possible de rediriger vers d'autres pages.
Exemple d'application
Feuille de calcul Todo
TodoTableComponent.razor:
- Comme ce composant n'a pas besoin de "@page" et "@layout" car il ne participera pas au routage et il utilisera la mise en page du composant parent
- Le code C # commence par le symbole @. En fait le même que dans Razor
@onclick=@(()=>ClickRow(item.Id))
Lie un événement de clic de ligne à la méthode ClickRow de notre ViewModel- Spécifiez les paramètres qui seront transférés du composant ou de la page parent au nôtre à l'aide de l'attribut [Parameter]
- Nous appelons la fonction de rappel reçue du composant parent. Ainsi, le composant parent apprend qu'un événement s'est produit chez l'enfant. Les fonctions peuvent uniquement être passées enveloppées dans EventCallback <> EventArgs paramétré. Une liste possible d'EventArgs peut être trouvée ici - docs.microsoft.com/ru-ru/aspnet/core/blazor/components?view=aspnetcore-3.0#event-handling
- Étant donné que la liste des types possibles d'EventArgs est limitée et que nous devons transmettre une propriété Id supplémentaire au gestionnaire d'événements du côté du composant parent, nous créons notre propre classe de paramètres héritée de la base et la transmettons à l'événement. Donc oui - dans le composant parent, le UIMouseEventArgs normal volera dans la fonction du gestionnaire d'événements et il devra être converti en notre type, par exemple, en utilisant l'opérateur as
Exemple d'utilisation:
<TodoTableComponent Items=@Items OnClick=@Select Current=@(Selected?.Id??Guid.Empty)></TodoTableComponent>
Page de suppression de Todo
Notre ViewModel aka VM est DeleteTodoViewModel.cs:
public class DeleteTodoViewModel : ComponentBase {
- Le paramètre de route "/ todo / delete / {id: guid}" est passé à Guid ici si nous allons, par exemple, à localhost / todo / delete / ae434aae44 ...
- Injectez des services du conteneur DI dans notre machine virtuelle.
- Juste une propriété de notre VM. Nous fixons nous-mêmes sa valeur, comme nous voulons.
- Cette méthode est appelée automatiquement lorsque la page est initialisée. Ici, nous définissons les valeurs nécessaires pour les propriétés de notre VM
- La méthode de notre VM. Nous pouvons le lier, par exemple, à l'événement de cliquer sur n'importe quel bouton de notre vue
- Aller sur une autre page située à l'adresse "/ todo" ie elle a au début la ligne "@page" / todo ""
Notre point de vue est DeleteTodo.razor:
- Nous indiquons que ce pays sera disponible à l'adresse {adresse racine de notre site} + "/ todo / delete /" + {une sorte de Guid}. Par exemple localhost / todo / delete / ae434aae44 ...
- Spécifiez que notre page sera rendue dans MainLayout.razor
- Spécifiez que notre page utilisera les propriétés et les méthodes de la classe DeleteTodoViewModel
- Nous précisons que lorsque vous cliquez sur ce bouton, la méthode Delete () de notre VM sera appelée
Todo Home
TodoViewModel.cs:
public class TodoViewModel : ComponentBase { [Inject] public ICommandDispatcher CommandDispatcher { get; set; } [Inject] public IQueryDispatcher QueryDispatcher { get; set; }
- Les attributs de validation standard de System.ComponentModel.DataAnnotations sont pris en charge. Plus précisément, nous indiquons ici que ce champ est obligatoire et le texte qui sera affiché si l'utilisateur ne spécifie pas de valeur dans l'entrée qui sera associée à ce champ.
- Méthode de gestion d'un événement avec un paramètre. Cette méthode gérera l'événement du composant enfant.
- Nous castons l'argument au type que nous avons créé dans le composant enfant
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 {
- Nous appelons le composant enfant et lui transmettons les propriétés et les méthodes de notre VM en tant que paramètres.
- Composant de formulaire intégré avec validation des données. Nous y indiquons qu'en tant que modèle, il utilisera notre VM et lors de l'envoi de données valides, il appellera sa méthode Create ()
- La validation sera effectuée à l'aide d'attributs de modèle tels que [Requared], etc.
- Ici, je vais afficher les erreurs générales de validation
- Créera une entrée avec validation. La liste des balises possibles est InputText, InputTextArea, InputSelect, InputNumber, InputCheckbox, InputDate
- Les erreurs de validation de la propriété de chaîne publique NewTodo {get; set;} seront affichées ici
- Lorsque vous cliquez sur ce bouton, l'événement OnValidSubmit de notre formulaire est déclenché
Fichier Startup.cs
Ici, nous enregistrons nos services
public class Startup { public void ConfigureServices(IServiceCollection services) {
Épilogue
Cet article a été écrit pour jouer l'appétit et encourager une étude plus approfondie de Blazor. J'espère avoir atteint mon objectif. Eh bien, pour mieux l'étudier, je recommande de lire le manuel officiel de Microsoft .
Remerciements
Merci à AndreyNikolin , win32nipuh , SemenPV pour les fautes d'orthographe et de grammaire trouvées dans le texte.