Dans cet article, nous explorons les nouvelles possibilités passionnantes de composants Web pour les développeurs d'applications Web et comment les bibliothèques de Brick et de X-Tag de Mozilla peuvent faciliter leur utilisation. Nous allons d'abord utiliser Brick pour prototyper rapidement une application simple. Ensuite, nous allons construire un composant web personnalisé en utilisant X-Tag.
Le problème des composants web
Il y a un problème avec le Web comme plate-forme pour les applications : HTML, le langage qui rend facile le balisage des documents et leur donne du sens n'a pas suffisamment d'éléments pour construire des applications. Il existe quelques nouveaux éléments dans la spécification HTML5, mais leur prise en compte est incomplète dans les navigateurs et il y a encore beaucoup de widgets manquants que d'autres plates-formes comme Flex ou iOS offrent aux développeurs out-of-the-box. En conséquence, les développeurs ont créé leurs propres "widgets" comme les barres de menus, commandes de curseur et calendriers à l'aide du HTML non-sémantique (la plupart du temps des éléments <div>). ils les ont rendus interactifs en utilisant le JavaScript et personnalisables en utilisant les CSS.
Cette solution de contournement est bonne, mais le problème est que nous ajoutons une couche sur la fonctionnalité des navigateurs au lieu d'étendre la manière dont elles fonctionnent déjà. En d'autres termes, un navigateur doit afficher le code HTML et le fait très bien en ayant un rendu d'au moins 60 images par seconde. Ensuite nous ajoutons notre propre widget de fonctionnalités et animons et modifions l'affichage sans en aviser le navigateur. Nous jonglons constamment avec les performances du navigateur et ajoutons celles de notre propre code. Cela conduit à des lags d'interfaces, à l'épuisement de la batterie et à des affichages instables.
La technologie
Tout d'abord, nous fournirons un aperçu des technologies concernées.
Brick : des composants web organisés
Mozilla Brick est un ensemble de composants d'interface utilisateur modulaires et réutilisables. Les composants sont conçus pour des applications adaptatives et sont un excellent choix pour développer pour le mobile d'abord, ce qui en gros est la façon dont les applications web devraient être développées. Cette philosophie et son modèle de conception accueillent une large gamme d'appareils. Les composants Brick ne sont pas seulement orientées pour les applications mobiles, ils sont créés pour les applications modernes.
Brick est un peu comme une bibliothèque, mais vraiment vous devriez le voir comme une collection organisée de composants web.
Tous les composants Brick sont utilisés de façon déclarative dans votre code HTML < comme-ça >
et peuvent être stylés avec un CSS comme n'importe quel élément non personnalisé. Les composants Brick ont leur propre micro-API pour interagir entre eux. Ces composants sont des blocs de construction. Vous aimez les Lego ? — eh bien vous aimerez Brick.
Les composants web de Brick sont créés en utilisant les éléments personnalisés permettant des fonctionalités non natives X-TAG.
Qu'est-ce que X-Tag?
X-Tag est une libraire qui permet certaines fonctionalités (et bientôt toutes) qui mettent à disposition des composants web pour le navigateur. En particulier, X-Tag se concentre sur la simulation de la création d'élements personnalisés pour que vous puissiez étendre de DOM en utilisant vos propres syntaxes déclaratives et API spécifiques à un élément.
Lorsque vous utilisez des composants de Brick, vous utilisez des composants web créés à l'aide de la bibliothèque de X-Tag. Brick inclut X-Tag, alors si vous incluez Brick et que vous décidez de créer votre propre élément personnel, vous n'avez pas besoin d'inclure X-Tag pour y parvenir : toutes les fonctionnalités de X-Tag sont déjà à votre disposition.
Démonstrations de travail
Télécharger les fichiers de projet de démo . Tout d'abord, nous allons utiliser le matériel qui se trouve dans le dossier simple-app-with-bricks.
Utiliser Bricks dans une application
Nous allons ici créer un squelette simple d'application en utilisant <x-appbar>
, <x-deck>
, et <x-card>
. x-appbar fournit une barre d'en-tête bien rangée pour notre application, et x-cards placé en tant qu'enfants d'un x-deck nous donne plusieurs vues avec des transitions.
Tout d'abord, nous commençons avec un document HTML dépouillé et nous y incluons le CSS et JS de Brick ainsi que le code de notre propre application (app.css
et app.js
respectivement dans les exemples qui suivent).
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <link rel="stylesheet" type="text/css" href="css/brick.min.css"> <link rel="stylesheet" type="text/css" href="css/app.css"> <title>Simple - Brick Demo</title> </head> <body> <!--- ici nous mettons des composants Brick --> <script type="text/javascript" src="js/brick.min.js"></script> <script type="text/javascript" src="js/app.js"></script> </body> </html>
Maintenant, nous allons ajouter quelques éléments de Brick :
<x-appbar id="bar"> <header>Simple Brick App</header> <button id="view-prev">Previous View</button> <button id="view-next">Next View</button> </x-appbar>
Enfin, au-dessous de x-appba
nous allons créer un x-deck
avec quelques x-carte
s en tant qu'enfants. Vous pouvez donner aux x-card
s le contenu que vous voulez.
<!-- Place your x-deck directly after your x-appbar --> <x-deck id="views"> <x-card> <h1>View 1</h1> <p>Hello, world!</p> </x-card> <x-card> <h1>Pick a Date</h1> <p><x-datepicker>s are a polyfill for <input type="date"></p> <x-datepicker></x-datepicker> <p>Just here to show you another tag in action!</p> </x-card> <x-card> <h1>A Random Cat To Spice Things Up</h1> <!-- Fetches from the Lorem Pixel placeholder content service --> <img src="https://lorempixel.com/300/300/cats"> </x-card> </x-deck>
Nous avons déjà presque terminé la structure pour une application simple. Tout ce dont nous avons besoin maintenant est un peu de CSS et de JavaScript pour tout lier. Tout d'abord, quelques lignes de simple JavaScript :
document.addEventListener('DOMComponentsLoaded', function() { // Run any code here that depends on Brick components being loaded first // Very similar to jQuery's document.ready() // Grab the x-deck and the two buttons found in our x-appbar and assign to local vars var deck = document.getElementById("views"), nextButton = document.getElementById("view-next"), prevButton = document.getElementById("view-prev"); // Add event listeners so that when we click the buttons, our views transition between one another prevButton.addEventListener("click", function(){ deck.previousCard(); }); nextButton.addEventListener("click", function(){ deck.nextCard(); }); });
Certains CSS simples pour rendre plus belle notre application naissante :
html, body { margin: 0; padding: 0; font-family: sans-serif; height: 100%; } h1 { font-size: 100%; } x-deck > x-card { background: #eee; padding: 0.6em }
Et voilà ! Avec un peu de balisage déclaratif et un peu de bricolage, nous avons un squelette que n'importe qui peut utiliser pour faire une application multi-vue en un seul document HTML. Si vous regardez les balises avec les outils de développement, vous verrez des éléments Brick cohabiter joyeusement avec les éléments de HTML classiques — vous pouvez utiliser les outils de développement pour les inspecter et les manipuler de la même manière que du bon vieux HTML.
Maintenant nous allons apprendre à faire notre propre élément personnalisé à l'aide de X-Tag.
Vos propres Bricks : créer des éléments personnalisés à l'aide de X-Tag
Disons que nous avons une application mobile dans laquelle l'utilisateur a une action qui se traduit par une tâche bloquante. Peut-être que l'application est en attente d'un service externe. La prochaine instruction pour réaliser la tâche demandée par l'utilisateur dépend de données qui viennent du serveur, nous devons malheureusement attendre. Pour les besoins de la cause, nous allons faire semblant de ne pas pouvoir beaucoup modifier notre programme et assumer une architecture bien établie - peut-être ne pouvons-nous pas faire grand-chose d'autre que de communiquer l'information à l'utilisateur jusqu'à ce que nous trouvions une façon de traiter au mieux avec le blocage. Nous devons faire au mieux avec ce que nous avons.
Nous allons créer une boite de dialogue personnalisée qui indiquera à l'utilisateur qu'il a besoin d'attendre pendant un petit moment. Il est important d'informer vos utilisateurs sur ce qui se passe dans votre application, quand ils n'obtiennent pas l'accomplissement de leur tâche dans le temps opportun : un utilisateur frustré ou confus peut abandonner l'utilisation de votre application.
Si vous suivez l'exemple, vous voudrez maintenant passer au dossier x-status-hud à l'interieur de la matière de la démo.
Enregistrement de votre élément personnalisé
X-Tag s'appuie sur différents événements pour détecter et mettre à niveau des éléments aux éléments personnalisés. X-Tag fonctionnera si l'élément était présent dans le document source original ajouté en définissant la propriété innerHTML
ou créé dynamiquement via document.createElement
. Vous devriez jeter un oeil à la Section des aides de la documentation X-Tag puisqu'elle couvre différentes fonctions qui vous permettront de travailler avec vos éléments personnalisés exactement comme ceux des éléments ordinaires.
La première chose que nous devons faire est d'inscrire notre élément personnalisé avec X-Tag pour que X-Tag sache quoi faire lorsqu'il rencontre notre élément personnalisé. Nous faisons cela en appelant xtag.register
:
xtag.register('x-status-hud', { // We will give our tag custom behavior here for our status indicating spinner });
Important : tous les noms des éléments personnalisés doivent contenir un trait d'union. Pourquoi ? L'idée ici est qu'il n'existe aucun élément HTML standard composé d'un trait d'union, en respectant cette règle, nous nous assurons que nous ne piétinerons pas les espaces de noms existants et éviterons des collisions. Il n'est pas nécessaire de préfixer les eléments avec un x-
: il s'agit juste d'une convention utilisée pour les composants créés avec X-Tag dans l'écosytème de Brick. Dans les premiers jours de la spécification du W3C pour les éléments personnalisés, Il a été spéculé que tous les éléments personnalisés auraient un préfixe x-
; Cette restriction a été assouplie dans les versions ultérieures de la spécification, ce qui signifie que <oeufs-mayonnaise>
et <chaton-mignon>
sont tous les deux noms parfaitement valides. Choisissez un nom qui décrit ce que votre élément est ou fait.
Si nous le voulions, nous pourrions choisir de définir quel élément HTML est utilisé comme élément de notre base avant la mise à niveau. Nous pourrions également définir un prototype spécifique pour notre élément si nous voulions impliquer la fonctionnalité à partir d'un autre élément. Vous pouvez déclarer ceci comme ci-dessous :
xtag.register('x-superinput', { extends: 'input', prototype: Object.create(HTMLInputElement.prototype) });
L'élément que nous construisons ne requiert pas explicitement la définition de ces propriétés, mais elles sont à noter car elles vous seront utiles lorsque vous écrirez des composants plus avancés et voudrez un certain niveau de contrôle sur eux.
Cycle de vie de l'élément
Les éléments personnalisés ont des événements qui se déclenchent à certains moments au cours de leur vie. Les événements sont déclenchés lorsqu'un élément est créé, inséré dans le DOM, enlevé du DOM, et lorsque ses attributs sont définis. Vous pouvez profiter d'aucun ou de tous ces événements.
lifecycle:{ created: function(){ // fired once at the time a component // is initially created or parsed }, inserted: function(){ // fired each time a component // is inserted into the DOM }, removed: function(){ // fired each time an element // is removed from DOM }, attributeChanged: function(){ // fired when attributes are set }
Notre élément va utiliser l'événement create
. Lorsque cet événement se déclenche, notre code ajoutera quelques éléments enfants.
xtag.register('x-status-hud', { lifecycle: { created: function(){ this.xtag.textEl = document.createElement('strong'); this.xtag.spinnerContainer = document.createElement('div'); this.xtag.spinner = document.createElement('div'); this.xtag.spinnerContainer.className = 'spinner'; this.xtag.spinnerContainer.appendChild(this.xtag.spinner); this.appendChild(this.xtag.spinnerContainer); this.appendChild(this.xtag.textEl); } } // More configuration of our element will follow here });
Ajout de méthodes personnalisées
Nous avons besoin d'avoir un contrôle lorsque nous montrons ou cachons notre statut HUD. Pour ce faire, nous devons ajouter des méthodes à notre composant. Un simple toggle()
pourrait suffir dans certains cas, mais nous allons utiliser les fonctions individuelles hide()
et show()
:
xtag.register('x-status-hud', { lifecycle: { created: function(){ this.xtag.textEl = document.createElement('strong'); this.xtag.spinnerContainer = document.createElement('div'); this.xtag.spinner = document.createElement('div'); this.xtag.spinnerContainer.className = 'spinner'; this.xtag.spinnerContainer.appendChild(this.xtag.spinner); this.appendChild(this.xtag.spinnerContainer); this.appendChild(this.xtag.textEl); } }, methods: { toggle: function(){ this.visible = this.visible ? false : true; }, show: function (){ this.visible = true; }, hide: function (){ this.visible = false; } }
Ajouter des fonctions personnalisées
Les propriétés des éléments personnalisés n'ont pas besoin de faire référence à un attribut. Cela est normal car certaines affectations pourraient être très complexes et n'ont pas un attribut significatif équivalent. Si vous désirez lier un attribut à une propriété, vous devrez passer par un objet vide littéral à l'attribut
. Dans le code ci-dessous, c'est ce qui a été fait pour l'attribut label
: les propriétés des éléments peronnalisés n'ont pas à être associées à un attrubut.
xtag.register('x-status-hud', { lifecycle: { created: function(){ this.xtag.textEl = document.createElement('strong'); this.xtag.spinnerContainer = document.createElement('div'); this.xtag.spinner = document.createElement('div'); this.xtag.spinnerContainer.className = 'spinner'; this.xtag.spinnerContainer.appendChild(this.xtag.spinner); this.appendChild(this.xtag.spinnerContainer); this.appendChild(this.xtag.textEl); } }, methods: { toggle: function(){ this.visible = this.visible ? false : true; }, show: function (){ this.visible = true; }, hide: function (){ this.visible = false; } }, accessors: { visible: { attribute: { boolean: true } }, label: { attribute: {}, set: function(text) { this.xtag.textEl.innerHTML = text; } } } }); // End tag declaration
Si la différence entre attributs et propriétés n'est pas claire pour vous, Stack Overflow fournit une bonne réponse. Bien que la question n'ait rien à voir (jQuery), la réponse du haut comporte une bonne explication qui vous aidera à comprendre la relation entre les attributs et propriétés.
Le composant fini
Lorsque nous écrivons du code qui dépend des éléments personnalisés ayant déjà été chargés, nous ajoutons un écouteur d'événements qui se déclenche lorsque les composants sont complètement chargés. C'est une sorte de document.ready
à la JQuery.
<script type="text/javascript"> document.addEventListener('DOMComponentsLoaded', function(){ // Any HUD customizations should be done here. // We just pop up the HUD here to show you it works! var testHUD = document.getElementById("test"); testHUD.label = "Please Wait..."; testHUD.show(); }, false); </script>
Et maintenant vous l'avez. Nous avons créé un simple widget modulaire et réutilisable pour notre code côté client.
Idées de rénovation
Notre widget est un bon point de départ, mais est-il vraiment achevé ? Il existe un certain nombre de façons dont nous pouvons l'améliorer :
- Faire en sorte que l'élément recalcule sa taille lorsque l'événement
attributeChanged
est déclenché ainsi que le redimensionner à la taille de l'étiquette quand il est mis à jour plutôt que de tronquer l'étiquette avec des points de suspension. - Laisser le développeur définir une image, comme un GIF animé, à la place de la toupie CSS (spinner) pour mieux personnaliser l'expérience utilisateur.
- Avoir une barre de progression au lieu d'une toupie pour donner à l'utilisateur des informations supplémentaires sur la progression des tâches.
Utilisez votre créativité pour créer un petit ensemble de fonctionnalité pratiques et d'améliorations grâce à cette page afin de faire vos propres exercices.