Article écrit par Victor Darras
Aujourd’hui un court article autour d’une petite nouveauté que nous délivre le créateur de VueJS. Nous allons découvrir (ou redécouvrir) ensemble une bibliothèque simple mais efficace inspirée du framework bien connu. À l’instar de VueJS, petite-vue nous permet de dynamiser des pages avec JavaScript pour en améliorer l’UX et la réactivité. Mais cette dernière se veut surtout plus légère, et s’oriente plutôt vers l’amélioration progressive de vos pages web comme pouvaient l’être jQuery ou Alpine ; elle ne requiert pas de build particulier et peut être importée avec une simple balise <script>
.
En bref, petite-vue
est une bibliothèque de moins de 5kb, développée par le créateur de VueJS et reprend dans les grandes lignes sa syntaxe et sa réactivité. Le projet n’en est encore qu’à ses balbutiements, mais plaira sans nul doute aux amateurs de VueJS (dont je fais partie).
Installation de la bibliothèque
Pour la simplicité de cet article, je vous invite à charger petite-vue
depuis un CDN ; il ne tient qu’à vous de la servir avec le reste du contenu de votre site pour la postérité.
<script src="https://unpkg.com/petite-vue" defer init></script>
Comme pour n’importe quel script, l’attribut defer
s’assurera de charger la source une fois l’ensemble du HTML interprété. L’attribut init
quant à lui est spécifique à petite-vue
et s’assure de l’initialiser une fois chargée. Pour notre exercice d’aujourd’hui, je vous montrerai comment initialiser un semblant de données, ce que nous ferons avant de monter notre « application », nous n’aurons donc pas besoin d’init
.
Mise en place des données
Pour cet article, j’ai voulu mettre en place un exercice rapide pour prendre en main quelques méthodes basiques ; il s’agira d’un générateur de box-shadow
unique.
Une fois chargé, commençons donc à construire une app simple avec createApp
qui prend en argument un ensemble de données, et un getter
, que nous utiliserons à la manière d’une computed. Nous aurons aussi une méthode copyToClipboard
, que je détaillerai un peu en fin d’article et n’est pas liée au fonctionnement de petite-vue
.
PetiteVue.createApp({
inset: false,
x: 5,
y: 5,
blur: 25,
spread: 0,
color: "#00000055",
copyText: "Copy",
get inlineStyle() {
return ` box-shadow: ${ this.inset ? 'inset' : '' } ${ this.x }px ${ this.y }px ${ this.blur }px ${ this.spread }px ${ this.color }; `;
},
copyToClipboard() { /* … */ }
}).mount()
On relie tous les fils ensemble
Passons maintenant au contenu HTML, nous allons avoir besoin d’un formulaire avec un champ pour chaque attribut de la future box-shadow :
<form>
<label for="inset">
<input id="inset" type="checkbox" v-model="inset">
Inset ?
</input>
</label>
<label for="offsetX">
Offset X
</label>
<input id="offsetX" max="100" min="0" type="range" v-model="x">
<label for="offsetY">
Offset Y
</label>
<input id="offsetY" max="100" min="0" type="range" v-model="y">
<label for="blur">
Blur
</label>
<input id="blur" type="range" v-model="blur">
<label for="spread">
Spread
</label>
<input id="spread" type="range" v-model="spread">
<label for="color">
Color
</label>
<input id="color" type="text" v-model="color">
</input>
</input>
</input>
</input>
</input>
</form>
Comme avec VueJS, nous pouvons mettre des attributs v-model
sur chaque input qui pointent vers les data définies précédemment.
Qu’est-ce que ça donne ?
Nous avons aussi besoin d’afficher le résultat de notre formulaire, en l’occurrence le style généré à la volée. On peut utiliser un attribut v-if
qui conditionnera l’affichage de la balise sur laquelle il est appliqué. Pour afficher les données, on utilisera (encore une fois) la même syntaxe que VueJS, soit les doubles accolade :
<h2 class="result">
<span v-if="inset">
inset
</span>
<span>
{{ x }}px
</span>
<span>
{{ y }}px
</span>
<span v-if="blur !== 0">
{{ blur }}px
</span>
<span v-if="spread !== 0">
{{ spread }}px
</span>
<span v-if="color">
{{ color }}
</span>
</h2>
Le rendu visuel
Afin de donner un peu de corps à notre générateur de box-shadow je vous propose de l’appliquer à la volée sur notre formulaire. Contrairement à VueJS, il n’y a pas la possibilité d’ajouter un attribut v-bind:style
(pour le moment peut-être ?); Il va nous falloir ruser, et je vous propose d’ajouter une balise <style>
dans laquelle on pourra appeler la méthode inlineStyle
:
<style>
form { {{ inlineStyle }} }
</style>
Un peu plus de confort, ça fait pas de mal
Pour aller un peu plus loin nous allons aussi permettre de copier le style généré en appelant notre méthode copyToClipboard
défini précédemment dans l’attribut v-bind:click
ou @click
. Dans mon exemple, j’ai mis ce bouton dans le formulaire qui serait donc soumis au click par défaut. J’ajoute .prevent
pour prévenir ce comportement.
<button @click.prevent="copyToClipboard()">
{{ copyText }}
</button>
Le contenu du bouton est dynamique, et défini dans nos data côté JavaScript. À chaque modification des données ; je vais vouloir redéfinir le contenu du bouton, je peux donc ajouter un événement change
sur le formulaire :
<form @change="copyText = 'Copy'" >
Revenons rapidement à notre JavaScript pour mettre en place la fonction de copie dans le presse-papier :
copyToClipboard() {
const el = document.createElement('textarea');
el.value = this.inlineStyle.trim();
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand("copy");
document.body.removeChild(el);
this.copyText = "copied";
}
Aperçu du résultat final !
Si tout se passe bien de votre côté (et je l’espère), en ajoutant quelques lignes de CSS vous devriez obtenir quelque chose qui ressemble à cet exemple sur CodePen :
See the Pen Box-shadow generator with petite-vue by Victor Darras (@victordarras) on CodePen.
Conclusion
J’ai vraiment apprécié petite-vue
pour ce petit exercice, la mise en place est rapide, la prise en main pour un utilisateur de VueJS est instantanée ; je n’ai fait que peu d’allers-retours dans la doc et j’arrive à un résultat intéressant en très peu de temps. Je n’ai évidemment pas abordé l’ensemble des possibilités de la bibliothèque, notamment la notion de scope par élément de DOM (puisque ici tout le document était dynamique) qui me parait essentiel pour ce genre d’usage ; mais ça fera peut-être l’objet d’un futur article ! Sachez en tout cas que bon nombre des fonctionnalités de VueJS sont retrouvables avec petite-vue
et que l’ensemble des différences sont présentées clairement sur le README du dépôt.
J’espère vous avoir donné un bon aperçu de ce que pouvait offrir cette mouture de VueJS orientée progressive enhancement et si tel est le cas, je vous invite à partager cet article autour de vous.