Présentation de Vuecket





Version russe

Vuecket est un framework Web qui intègre VueJS côté client et Apache Wicket côté serveur. Il prend le meilleur des deux et rend le développement d'applications full-stack encore plus rapide et plus facile. Bien sûr, ce sont tous de grands mots, car Vuecket a actuellement (août 2020) moins d'un mois, et il n'a pas encore passé le baptême de serveurs de production "feu et sang". Mais il a déjà inclus tout le meilleur que nous avons développé lors du développement de notre produit clé Open Source Orienteer (une plate-forme pour le développement rapide d'applications métier). Et c'est justement à cause de son jeune âge que Vuecket a besoin de votre aide: partagez ce que vous avez aimé, ce qui n'est pas très bon, où des améliorations sont nécessaires, etc.



Les principes de base qui nous guident lors de la construction de Vuecket sont:



  1. Être déclaratif n'est pas impératif. Vuecket ne dicte aucune exigence de code particulière. Il peut être appliqué assez rapidement et facilement aux projets Vue.JS ou Apache Wicket existants.
  2. Suivez le principe de Pareto. Vuecket devrait fournir 80% des fonctionnalités que vous souhaitez prêtes à l'emploi, mais il devrait y avoir des points d'extension bons et pratiques pour les 20% restants.


Il est facile de voir que ces principes s'appliquent également à Vue.JS et Apache Wicket.



Alors, comment allons-nous commencer avec Vuecket? Je suggère de créer un forum de discussion / d'invité avec le support Markdown. Je ne vais pas trop tourmenter: l'application terminée est , et le code est .



Nous créons un projet



Générons notre projet via `mvn archetype: generate`. Pour ce faire, vous pouvez utiliser, par exemple, la commande suivante:



mvn archetype:generate -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=8.9.0 -DgroupId=com.mycompany -DartifactId=mychat -DarchetypeRepository=https://repository.apache.org/ -DinteractiveMode=false


Vuecket n'a pas encore son propre modèle de projet Maven. Peut-être ajouterons-nous cela à l'avenir . Maintenant, connectons Vuecket lui-même. Ajoutez la dépendance suivante au projet `pom.xml`:



<dependency>
	<groupId>org.orienteer.vuecket</groupId>
	<artifactId>vuecket</artifactId>
	<version>1.0-SNAPSHOT</version>
</dependency>


Sortie de texte dans Markdown



Le projet Wicket contient déjà une page d'accueil Wicket par défaut. Ajoutons-y du code pour nous assurer que Vuecket fonctionne déjà. Par exemple, affichons Hello World, mais dans Markdown, et pour que le texte lui-même soit défini côté serveur dans le composant Apache Wicket. Nous utiliserons la bibliothèque vue-markdown pour rendre Markdown .



Dans HomePage.html, au lieu du message d'accueil Wicket, ajoutez:



<div wicket:id="app">
	<vue-markdown wicket:id="markdown">This will be replaced</vue-markdown>
</div>


Et dans HomePage.java le code suivant:



public HomePage(final PageParameters parameters) {
	super(parameters);
	add(new VueComponent<String>("app")
			.add(new VueMarkdown("markdown", "# Hello World from Vuecket")));
}


Mais où est la classe VueMarkdown? Et nous le définirons comme suit:



@VueNpm(packageName = "vue-markdown", path = "dist/vue-markdown.js", enablement = "Vue.use(VueMarkdown)")
public class VueMarkdown extends Label {
	public VueMarkdown(String id) {
		super(id);
	}
	public VueMarkdown(String id, Serializable label) {
		super(id, label);
	}
}


Faites attention à l'annotation @VueNpm. Il est nécessaire d'activer Vuecket sur ce composant Wicket, qui chargera tout ce dont NPM a besoin pour aider le navigateur à restituer correctement le composant déjà Vue pour Markdown.



Si vous avez tout fait correctement, après avoir démarré le projet via `mvn jetty: run`, vous devriez voir quelque chose comme ça sur http: // localhost: 8080




Alors que s'est-il passé ici et pourquoi ça marche?



  • Nous avons balisé la page en y ajoutant 2 composants Vue: pour l'application et pour la sortie Markdown
  • Nous avons regroupé des composants Vue avec des composants Wicket côté serveur (dans HomePage.java)
  • Nous avons dit à Vuecket de quelle bibliothèque Vue.JS il a besoin pour rendre 'vue-markdown'
  • Et puis tout est simple: Wicket, lors du rendu de la page dans le navigateur, a utilisé la ligne «# Hello World from Vuecket», que nous avons définie lors de l'ajout du composant Wicket, et Vuecket a aidé le navigateur à charger les bibliothèques VueJS nécessaires, à lancer l'application VueJS et à rendre le message d'accueil déjà comme rendu Markdown


Github s'engage à vous aider



Saisir un message et le prévisualiser



Dans cette étape, nous compliquerons notre application: nous ferons la saisie du message et son aperçu.

Ajoutons une zone de texte à HomePage.html pour entrer un message, ainsi que lier ce champ et vue-markdown à la variable "text" de VueJS.



<div wicket:id="app">
	<textarea v-model="text" style="width:100%" rows="5"></textarea>
	<vue-markdown wicket:id="markdown" :source="text">Will be replaced</vue-markdown>
</div>


Nous utilisons déjà la variable "text", mais nous devons maintenant l'ajouter au composant de données Vue. Il existe plusieurs façons de le faire dans Vuecket, mais allons-y pour le plus longtemps:



  • Créez votre propre application VueComponent for Vue
  • Associons-le à notre fichier * .vue
  • Écrivons la logique dans le fichier * .vue: pour l'instant, juste le champ "texte"


Voici quelques-uns des changements que nous apporterons:



//HomePage.java:
public HomePage(final PageParameters parameters) {
	super(parameters);
	add(new ChatApp("app")
			.add(new VueMarkdown("markdown")));
}
//ChatApp.java:
@VueFile("ChatApp.vue")
public class ChatApp extends VueComponent<Void> {
	public ChatApp(String id) {
		super(id);
	}
}


Eh bien, ChatApp.vue lui-même:



<script>
module.exports = {
    data: function() {
        return {
            text : ""
        }
    }
}
</script>


En conséquence, lorsque vous démarrez `mvn jetty: run` et entrez du texte, vous pouvez voir ce qui suit




Dans ce chapitre, nous avons appris comment: créer des fichiers * .vue familiers et les associer aux composants Apache Wicket



GitHub commit pour vous aider



Afficher une liste de messages et en ajouter un nouveau



Il n'y aura rien de spécifique à Vuecket ou Wicket dans ce chapitre: le pur éclat de VueJS.

Si nous décomposons la tâche, nous devrons alors effectuer les opérations suivantes:



  • Ajouter une zone de liste à notre application Vue pour enregistrer les messages
  • Ajouter une méthode pour ajouter un nouveau message à la liste
  • Affichez une liste de messages et n'oubliez pas la démarque


Tout d'abord, changeons notre ChatApp.vue et ajoutons la logique nécessaire: un nouveau champ `messages` avec une liste de messages et la méthode ʻaddMessage` pour ajouter un nouveau message. Et n'oublions pas que lors de l'ajout d'un message à la liste, c'est une bonne idée d'effacer le champ de saisie d'origine. Pour les messages, nous stockerons non seulement le texte, mais également la date d'ajout / d'envoi. À l'avenir, il sera possible d'étendre avec des champs supplémentaires, par exemple, qui a envoyé ce message, priorité, mise en évidence requise, etc.



<script>
module.exports = {
    data: function() {
        return {
            text : "",
            messages: []
        }
    },
    methods: {
    	addMessage : function() {
    		this.messages.push({
    			message: this.text,
    			date: new Date()
    		});
    		this.text = "";
    	}
    }
}
</script>


Nous allons également modifier HomePage.html, ajouter un affichage de la liste des messages et ajouter un appel à notre méthode addMessage en appuyant sur Ctrl-Entrée.



<div wicket:id="app">
	<div v-for="(m, index) in messages">
		<h5>{{ index }}: {{ m.date }}</h5>
		<vue-markdown :source="m.message"></vue-markdown>
	</div>
	<textarea v-model="text" 
			  style="width:100%" 
			  rows="5" 
			  @keyup.ctrl.enter="addMessage"
			  placeholder="Enter message and Ctrl-Enter to add the message">
	 </textarea>
	<vue-markdown wicket:id="markdown" :source="text">Will be replaced</vue-markdown>
</div>


Lorsque vous exécutez `mvn jetty: run` et entrez quelques messages, vous verrez quelque chose comme ça




Dans ce chapitre, nous avons seulement appris à l'application utilisant VueJS à ajouter un message à la liste et à afficher cette dernière.



GitHub s'engage à vous aider



Activez la collaboration



Si auparavant le contenu de notre livre d'or était unique pour chaque visiteur de la page, alors dans ce chapitre nous activerons la communication avec le serveur et autoriserons la synchronisation avec tous les visiteurs. Pour cela, nous avons besoin de Vuecket Data Fibers, une solution qui permet aux objets côté navigateur d'être synchronisés avec les objets côté serveur. Et le plus intéressant est que nous n'avons rien à faire pour cela du côté client! Cela paraît bien? Allons coder! Bien que ... Il n'y a que deux nouvelles lignes dans notre composant ChatApp.java:



private static final IModel<List<JsonNode>> MESSAGES = Model.ofList(new ArrayList<JsonNode>());

public ChatApp(String id) {
	super(id);
	addDataFiber("messages", MESSAGES, true, true, true);
}


Que s'est-il passé ici:



  • Nous avons créé un modèle MESSAGES accessible à tous, puisqu'il est créé en tant que final statique.
  • Ajout de la fibre de données, qui lie l'objet messages côté client et l'objet à l'intérieur du modèle MESSAGES côté serveur.
  • , data-fiber 3 : load, observe, refresh. Load — , Observe — , Refresh — .


-




GitHub commit





Dans le chapitre précédent, j'ai un peu triché en accordant un accès en lecture / écriture à la collection de messages à tous les visiteurs du site à la fois. Il est fortement déconseillé de le faire, car alors, grâce à la fibre de données, tout expéditeur peut écraser tous les messages sur le serveur par quelque chose qui lui est propre ou même les effacer. Les fibres de données ne doivent être utilisées que pour lier des objets personnalisés côté navigateur à des objets de données côté serveur appartenant au même utilisateur. Cela signifie pas de modèles ou de données statiques!



Comment pouvons-nous régler la situation? Pour cela, nous devons:



  • Abandonnez la fibre de données, qui fonctionne à tous les niveaux, et ne l'utilisez que pour charger initialement la liste de messages.
  • Utilisez la méthode côté serveur pour ajouter un nouveau message à la liste.


Ainsi, tout le monde ne peut ajouter que de nouveaux messages à la liste générale, mais ne peut ni supprimer ni modifier les messages existants. Compliquons également un peu le côté serveur: nous enregistrerons non seulement JSON reçu du client, mais une classe Message spécialisée avec les champs, méthodes, etc. nécessaires. pour travailler avec des données côté serveur.



Commençons par une classe Message pour stocker les messages des utilisateurs. Cela peut être une classe JPA, au fait, qui vous permet d'enregistrer des données dans une base de données.



public class Message implements IClusterable {
	@JsonProperty("message")
	private String text;
	private Date date;
	
	public String getText() {
		return text;
	}
	public void setText(String text) {
		this.text = text;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}	
}


Faites attention à @JsonProperty. Ainsi, nous avons redirigé le champ JSON "message" vers notre champ Java "texte".



Ensuite, modifions ChatApp.java pour faire ce qui est décrit ci-dessus: ajoutez une méthode vuecket pour enregistrer le message. Aussi, dans le code, vous pouvez remarquer la réduction de la liste des messages à seulement 20 (les utilisateurs Habr sont très assidus), mais lorsque vous supprimez un message, il est toujours sauvegardé à jamais dans les journaux du serveur.



@VueFile("ChatApp.vue")
public class ChatApp extends VueComponent<Void> {
	
	private static final Logger LOG = LoggerFactory.getLogger(ChatApp.class);
	private static final int MAX_SIZE = 20;
	private static final IModel<List<Message>> MESSAGES = Model.ofList(new ArrayList<Message>());

	public ChatApp(String id) {
		super(id);
		addDataFiber("messages", MESSAGES, true, false, false);
	}
	
	@VueMethod
	public synchronized void addMessage(Context ctx, Message message) {
		List<Message> list = MESSAGES.getObject();
		list.add(message);
		trimToSize(list, MAX_SIZE);
		IVuecketMethod.pushDataPatch(ctx, "messages", list);
	}
	
	private void trimToSize(List<Message> list, int size) {
		//It's OK to delete one by one because in most of cases we will delete just one record
		while(list.size()>size) LOG.info("Bay-bay message: {}", list.remove(0));
	}
}


Voir la méthode d'annotation @VueMethod? Dans celui-ci, nous recevons un nouveau message, l'enregistrons dans la liste, le coupons et envoyons la liste déjà mise à jour au client. Notez également que la fibre de données a été reconfigurée pour ne demander des données qu'au démarrage de l'application Vue.



Nous devons également changer la logique dans ChatApp.vue afin qu'au lieu du champ "messages" local, envoyez un nouveau message au serveur en mode asynchrone (vcInvoke)



module.exports = {
    data: function() {
        return {
            text : "",
            messages: []
        }
    },
    methods: {
    	addMessage : function() {
    		this.vcInvoke("addMessage", {
    			message: this.text,
    			date: new Date()
    		});
    		this.text = "";
    	}
    }
}


Ce que nous avons appris du chapitre:



  • Comment créer des méthodes côté serveur pour Vuecket
  • Comment appeler des méthodes sur le serveur à partir d'un navigateur
  • Comment envoyer les modifications souhaitées au client


Pour un visiteur respectueux des lois, rien n'a changé, mais un hacker ne peut plus changer aussi facilement la liste générale des messages sur le serveur




GitHub s'engage à vous aider



Conclusion



À ce sujet aujourd'hui, permettez-moi de terminer. Il y a beaucoup d'autres améliorations qui peuvent être apportées à notre code, mais je vous laisse cela à vous, chers lecteurs. Si vous avez besoin d'aide, écrivez, nous vous aiderons!



Aimez-vous le cadre? Veuillez partager votre opinion. Après tout, vous pensez que l'Open Source vit et se développe.



Spoiler des améliorations à venir de Vuecket
  • WebSocket' .
  • , .
  • data-fiber' .
  • Vuecket/Wicket , VueJS , , Markdown





All Articles