Nell'articolo https://www.html5italia.com/articoli/frontend/confronto-react-angular-svelte-vue.aspx abbiamo parlato dei principali framework o librerie, attualmente presenti sul mercato, che potremmo prendere in considerazione per lo sviluppo di una applicazione front-end. In questo script aggiungeremo un tassello che potremmo definire fondamentale in termini architetturali: andremo a creare un'architettura definita "Presentational e Container components". Tale sistema è utile, all'interno delle applicazioni front-end a suddividere i componenti che eseguono operazioni sui dati da quelli incaricati di mostrare un'interfaccia utente. Per fare un paragone con il mondo back-end, stiamo creando due sotto-categorie di componenti, una che si occuperà del Presentation Layer e una che gestirà la Business Logic.
Benchè questo livello di dettaglio non è richiesto da nessuno dei framework trattati, è bensì utile a noi sviluppatori, in quanto ci consente di creare dei componenti UI riutilizzabili al 100%, le cui uniche dipendenze sono i valori ricevuti come input. Allo stesso modo avere dei componenti che gestiscano tutte le chiamate ai servizi, o la trasformazione dei dati, prima di essere presentati a monitor.
In questo script andremo ad analizzare come condividere i dati verso il presentational component e come notificare il container riguardo un'azione effettuata dall'utente. In tutti gli esempi presenteremo una lista di elementi e un bottone, che a seguito di un click, invia al container una stringa "Ciao Mondo!".
Presentational e container in Angular
La comunicazione tra componenti, in Angular, viene effettuata tramite le direttive Input e Output. Partiamo con il preparare un componente che generi una lista e predisponga un metodo per gestire un evento emanato dal componente che andrà a presentare
import { Component } from "@angular/core"; @Component({ selector: "my-app", template: `<component-one [list]="list" (evnt)="handle($event)"></component-one>` }) export class AppComponent { list: number[] = [1, 2, 3, 4]; handle(e) { console.log(e); } }
Continuiamo con la creazione del componente di UI in modo tale che accetti come input una proprietà list ed emetta un evento tramite evnt
import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ selector: 'component-one', template: `<ul> <li <i>ngFor="let item of list">{{item}}</li> </ul> <button (click)="btnClick()">Click</button>`, }) export class HelloComponent { @Input() list: number[]; @Output() evnt: EventEmitter<string> = new EventEmitter(); btnClick(){ this.evnt.emit('Ciao Mondo!'); } }
Presentational e container in React
Con React la condivisione di variabili ed eventi è semplicemente gestita da normali variabili o funzioni, senza la necessità di alcuna direttiva che specifichi i parametri in input o output tra i componenti.
Il container sarà così strutturato
import React, { useState } from 'react'; import Component from "./Component" export default function App() { const [state, setState] = useState([1,2,3,4]); function handle(e){ console.log(e); } return ( <div> <Component list={state} evnt={handle}></Component> </div> ); }
A seguito dell'import di Component stabiliamo che la proprietà in input sarà passata attraverso il nome di list e l'output sarà collezionato da evnt che chiamerà la funzione handle. Prestando attenzione a mantenere gli stessi nomi, andiamo a creare il presentational component, utilizzando la variabile props come aggregatore dei parametri provenienti dal container component
export default function Component(props) { function btnClick() { props.evnt('Ciao Mondo!') }; return ( <div> <ul> {props.list.map((value, index) => { return <li key={index}>{value}</li> })} </ul> <button onClick={btnClick}> Click </button> </div> ); }
Presentational e container in Vue
Iniziando sempre dal container, sapendo che la sintassi di Vue somiglia molto a quella di React, possiamo convertire il codice che abbiamo scritto in precedenza. L'unica accortezza da seguire è l'utilizzo degli attributi v-bind e v-on all'interno dell'HTML: la sintassi che trovavamo in React, trascritta in Vue, permette solo il passaggio di stringhe, per oggetti complessi è necessario usare degli attributi specifici
<template> <div id="app"> <Component v-bind:list="list" v-on:evnt="handle"/> </div> </template> <script> import Component from './Component.vue' export default { name: 'App', components: { Component }, data: ()=>({ list: [1,2,3,4] }), methods: { handle: function (e) { console.log(e) } } } </script>
La stessa procedura può essere applicata anche al presentational component, prestando attenzione a dichiarare i parametri in input in maniera esplicita all'interno della proprietà props. Per emettere un evento, invece, non occorrerà specificare nulla, in quanto è già disponibile in ogni componente Vue il metodo $emit che consente, fornendo un nome e opzionalmente dei parametri, di emettere appunto eventi.
<template> <ul v-for="item in list"> {{item}} </ul> <button v-on:click="btnClick"> Click </button> </template> <script> export default { name: 'Component', props: ['list'], methods: { btnClick: function (e) { this.$emit('evnt', 'Ciao Mondo!') } } } </script>
Il codice scritto in Vue rispetta le aspettative: richiede meno architettura dell'esempio in Angular: non avendo alcuna tipizzazione per variabili in input e addirittura nessun parametro per l'output. Allo stesso tempo, l'utilizzo di props, e la differenziazione tra gli attributi HTML, porta ad avere un livello di controllo maggiore rispetto a React
Presentational e container in Svelte
Dall'introduzione a Svelte, fatta nell'articolo precedente, possiamo aspettarci solo semplicità e velocità di scrittura. Il container avrà la struttura seguente
<script> import Component from './Component.svelte'; let list = [1,2,3,4]; function handle(e){ console.log(e.detail) } </script> <Component on:evnt={handle} list={list}/>
Le parti su cui porre la nostra attenzione sono quelle riguardanti la gestione degli eventi. Se infatti il passaggio di parametri ricorda molto React, per gli eventi è necessario utilizzare l'attributo on:nome-evento, per recuperare poi il valore emesso dobbiamo utilizzare la proprietà detail presente nell'evento ricevuto nel metodo come input.
Anche per il presentation component la sintassi risulta molto pulita, eccezion fatta per gli eventi, anche in questo caso abbiamo la necessità di scrivere alcune righe di codice per creare un generatore di eventi tramite la funzione createEventDispatcher.
<script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); export let list; function btnClick() { dispatch('evnt', 'Ciao Mondo!'); } </script> <ul>{#each list as item} <li>{item}</li> {/each} </ul> <button on:click={btnClick}>Click</button>
Ora che sappiamo come collegare i componenti all'interno della pagina, nei prossimi script vedremo come collegare più pagine e recuperare dati provenienti da REST API.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare la versione generica di EntityTypeConfiguration in Entity Framework Core
Implementare il throttling in ASP.NET Core
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
Usare il colore CSS per migliorare lo stile della pagina
Cancellare una run di un workflow di GitHub
Creare una custom property in GitHub
Implementare l'infinite scroll con QuickGrid in Blazor Server
Gestire la cancellazione di una richiesta in streaming da Blazor
Registrare servizi multipli tramite chiavi in ASP.NET Core 8
Usare lo spread operator con i collection initializer in C#
Effettuare il binding di date in Blazor
Sostituire la GitHub Action di login su private registry