Dans ce tutoriel, nous allons utiliser Hyperapp pour créer une application de liste de tâches. Si vous voulez apprendre les principes de la programmation fonctionnelle, mais ne vous embourbez pas dans les détails, poursuivez votre lecture.
Hyperapp est très chaud en ce moment. Il a récemment dépassé 11,000 étoiles sur GitHub et a obtenu la 5ème place dans la section Front-end Framework des 2017 Rising Stars . Il a également été présenté sur SitePoint récemment, quand il a frappé la version 1.0.
La popularité de Hyperapp peut être attribuée à son pragmatisme et sa taille ultralégère (1,4 kB), tout en obtenant des résultats similaires pour réactualiser et Redux hors de la boîte.
Alors, qu'est-ce que HyperApp?
Hyperapp vous permet de créer des applications Web dynamiques d'une page en tirant parti d'un DOM virtuel pour mettre à jour les éléments sur une page Web rapidement. efficacement d'une manière similaire à React. Il utilise également un seul objet qui est responsable du suivi de l'état de l'application, tout comme Redux. Cela facilite la gestion de l'état de l'application et permet de s'assurer que les différents éléments ne sont pas synchronisés les uns avec les autres. L'influence principale derrière Hyperapp était l'architecture d'orme .
À la base, Hyperapp a trois parties principales: État . C'est un arbre d'objets unique qui stocke toutes les informations sur l'application.
state
et actions
. Ces trois parties interagissent entre elles pour produire une application dynamique. Les actions sont déclenchées par des événements sur la page. L'action met ensuite à jour l'état, ce qui déclenche ensuite une mise à jour de la vue. Ces modifications sont apportées au DOM virtuel, que Hyperapp utilise pour mettre à jour le DOM réel sur la page Web.
Mise en route
Pour commencer le plus rapidement possible, nous allons utiliser CodePen pour développer notre application. Vous devez vous assurer que le préprocesseur JavaScript est défini sur Babel et que le package Hyperapp est chargé en tant que ressource externe à l'aide du lien suivant:
https://unpkg.com/hyperapp
Pour utiliser Hyperapp, nous devons importer la fonction app
ainsi que la méthode h
que Hyperapp utilise pour créer des nœuds VDOM. Ajoutez le code suivant au volet JavaScript dans CodePen:
const {h, app} = hyperapp;
Nous utiliserons JSX pour le code de vue. Pour être sûr que Hyperapp le sache, nous devons ajouter le commentaire suivant au code:
/ ** @jsx h * /
La méthode app ()
est utilisée pour initialiser l'application:
const main = app (état, actions, vue, document.body);
Cela prend les deux premiers paramètres de l'état Pour faciliter le démarrage, j'ai créé un modèle de code Hyperapp à chaud sur CodePen qui contient tous les éléments mentionnés ci-dessus. Il peut être forké par en cliquant sur ce lien Jouons avec Hyperapp et voyons comment tout cela fonctionne. La fonction Cela retournera réellement l'objet VDOM suivant: La fonction Les composants sont des fonctions pures qui renvoient des nœuds virtuels. Ils peuvent être utilisés pour créer des blocs de code réutilisables qui peuvent ensuite être insérés dans la vue. Ils peuvent accepter des paramètres de la manière habituelle que n'importe quelle fonction peut avoir, mais ils n'ont pas accès aux objets Dans l'exemple ci-dessous, nous créons un composant appelé On peut maintenant se référer à ce composant dans la vue comme s'il s'agissait d'un élément HTML intitulé . Nous pouvons transmettre des données à cet élément de la même manière que nous pouvons transmettre des accessoires à un composant React: Notez que, lorsque nous utilisons JSX, les noms de composants doivent commencer par des lettres majuscules ou contenir un point L'état est un simple objet JavaScript qui contient des informations sur l'application. C'est la "source unique de vérité" pour l'application et ne peut être modifiée qu'en utilisant des actions. Créons l'objet state pour notre application et définissons une propriété appelée La fonction de vue a maintenant accès à cette propriété. Mettez à jour le code comme suit: Puisque la vue peut accéder à l'objet Les actions sont des fonctions utilisé pour mettre à jour l'objet d'état. Ils sont écrits sous une forme particulière qui renvoie une autre fonction, curryte, qui accepte l'état actuel et renvoie un objet d'état partiel mis à jour. Ceci est en partie stylistique, mais assure également que l'objet L'exemple ci-dessous montre comment créer une action appelée Pour voir cette action, nous pouvons créer un bouton dans la vue et utiliser un gestionnaire d'événement Maintenant, essayez de cliquer sur le bouton et regardez le nom changer Vous pouvez voir un exemple en direct ici Maintenant, il est temps de construire quelque chose de plus substantiel. Nous allons créer une application de liste de tâches simple qui vous permet de créer une liste, d'ajouter de nouveaux éléments, de les marquer comme complets et de supprimer des éléments. Tout d'abord, nous allons devoir démarrer un nouveau stylo sur CodePen. Ajoutez le code suivant ou montez simplement mon crayon HyperBoiler: Vous devez également ajouter ce qui suit dans la section CSS et le définir sur SCSS: Il suffit d'ajouter un peu de style et d'image de marque Hyperapp à l'application. Passons maintenant à la construction de l'application actuelle Pour commencer, nous allons mettre en place l'état initial Lors de la création de l'objet initial Ensuite, nous allons créer la fonction Ceci affichera un titre, ainsi qu'un élément appelé . Ce n'est pas un nouvel élément HTML, mais un composant que nous devrons créer. Faisons-le maintenant: Ceci renvoie un élément Comme vous pouvez vous y attendre, la fonction Notez que les fonctions Vous pouvez également voir que la propriété Pour coller tout ensemble, nous devons ajouter l'action Maintenant, si vous commencez à taper dans le champ de saisie, vous devriez voir qu'il affiche ce que vous tapez. Ceci illustre la boucle Hyperapp: Essayez et vous devriez voir ce qui est tapé apparaître dans le champ de saisie. Malheureusement, en appuyant sur Entrez ou en cliquant sur le bouton "+" ne fait rien pour le moment. C'est parce que nous devons créer une action qui ajoute des éléments à notre liste. Avant de créer un élément de liste, nous devons réfléchir à la façon dont ils seront représentés. La notation d'objet de JavaScript est parfaite, car elle nous permet de stocker des informations en tant que paires clé-valeur. Nous devons réfléchir aux propriétés d'un élément de liste. Par exemple, il a besoin d'une valeur qui décrit ce qui doit être fait. Il a également besoin d'une propriété qui indique si l'élément a été complété ou non. Un exemple pourrait être: Notez que l'objet contient également une propriété appelée Nous pouvons maintenant créer une action pour ajouter des éléments. Notre premier travail consiste à réinitialiser le champ de saisie pour qu'il soit vide. Cela est effectué en réinitialisant la propriété d'entrée Notez que cette action contient deux états différents. Il y a l'état actuel représenté par l'argument fourni à la deuxième fonction. Il y a aussi le nouvel état qui est la valeur de retour de la deuxième fonction Pour démontrer cela en action, imaginons que l'application vient de commencer avec une liste vide d'éléments et qu'un utilisateur a entré le texte " Acheter du lait "dans le champ de saisie et appuyer sur Entrez déclenchant l'action Avant l'action, l'état ressemble à ceci: Cet objet est passé en argument de l'action Maintenant nous pouvons ajouter des éléments au tableau Ceci utilise un élément Maintenant que nous avons un composant pour nos éléments de liste, nous devons les afficher. JSX rend cela très simple, car il va parcourir un ensemble de valeurs et les afficher tour à tour. Le problème est que Cela va parcourir chaque objet dans le tableau Cela place simplement le nouveau tableau de Maintenant, si vous essayez d'ajouter des éléments, vous devriez les voir apparaître dans une liste sous le champ de saisie! Notre prochain travail est de pouvoir basculer la propriété Cela peut être fait en utilisant l'action suivante: Il se passe pas mal de choses dans cette action. Tout d'abord, il accepte un paramètre appelé Maintenant, nous devons câbler cette action à la vue. Nous faisons cela en mettant à jour le composant Les yeux d'aigle parmi vous auront remarqué que le composant a gagné des paramètres supplémentaires et qu'il y a aussi du code supplémentaire dans la liste des attributs Il s'agit d'un modèle courant dans Hyperapp qui est utilisé pour insérer des fragments de code supplémentaires lorsque certaines conditions sont vraies. Il utilise court-circuit ou paresseux évaluation pour définir la classe comme terminée si l'argument Notre dernier travail consiste à mettre à jour le code dans la fonction Maintenant, si vous ajoutez des éléments et que vous essayez de cliquer dessus, vous devriez voir qu'ils sont marqués comme complets, avec une ligne qui les traverse. Cliquez à nouveau et ils reviennent à incomplète. Notre application de liste fonctionne assez bien pour l'instant, mais il serait bon que nous puissions supprimer tous les éléments dont nous n'avons plus besoin dans la liste. 19659003] Notre premier travail consiste à ajouter une action Ajoutez le code suivant à l'objet Nous devons maintenant mettre à jour le composant Notez que nous devons également ajouter un autre paramètre appelé Enfin, nous devons mettre à jour la vue pour passer Maintenant, si vous ajoutez des éléments à votre liste, vous devriez remarquer le bouton "x" lorsque vous les survolez. Cliquez sur ceci et ils devraient disparaître dans l'éther! La dernière fonctionnalité que nous ajouterons à notre application de liste est la possibilité de supprimer toutes les tâches terminées à la fois. Cela utilise la même méthode Pour l'implémenter, il suffit d'ajouter un bouton avec un gestionnaire d'événement Essayez maintenant d'ajouter quelques éléments, marquez quelques-uns d'entre eux comme étant complets, puis appuyez sur le bouton pour les effacer tous. Voir le Pen Hyperlien par SitePoint ( @SitePoint ) le CodePen . Cela nous amène à la fin de ce tutoriel. Nous avons mis en place une application de liste de tâches simple qui fait la plupart des choses que vous attendez d'une telle application. Si vous êtes à la recherche d'inspiration et que vous voulez ajouter de la fonctionnalité, vous pouvez ajouter des priorités, modifier l'ordre des éléments à l'aide du glisser-déposer ou ajouter la possibilité d'avoir plusieurs listes. J'espère que tutoriel vous a aidé à comprendre comment fonctionne Hyperapp. Si vous voulez creuser un peu plus profond dans Hyperapp, je recommanderais en lisant les docs et en jetant un coup d'oeil au code source . Ce n'est pas très long, et vous donnera un aperçu utile de la façon dont tout fonctionne en arrière-plan. Vous pouvez également poser d'autres questions sur le groupe Hyperapp Slack . C'est l'un des groupes les plus sympathiques que j'ai utilisés, et les membres bien informés m'ont beaucoup aidé. Vous découvrirez également que Jorge Bucaran le créateur d'Hyperapp, est souvent là pour vous aider et vous conseiller. Utiliser CodePen rend le développement d'applications Hyperapp très rapide et facile, mais vous finirez par vouloir construire vos propres applications localement et les déployer également en ligne. Pour des conseils sur la façon de faire cela, consultez mon prochain article sur regroupant une application Hyperapp et le déployant sur des pages GitHub ! J'espère que vous apprécierez de jouer avec le code de cet article, et partagez s'il vous plaît
et actions
la fonction view ()
comme troisième paramètre, et le dernier paramètre est le Élément HTML où l'application doit être insérée dans votre balisage. Par convention, il s'agit généralement de l'étiquette représentée par
document.body
.
Hello Hyperapp!
view ()
accepte les objets state
et actions
comme arguments et renvoie un objet DOM virtuel. Nous allons utiliser JSX, ce qui signifie que nous pouvons écrire du code qui ressemble beaucoup plus au HTML. Voici un exemple qui va retourner un en-tête: const view = (état, actions) => (
Bonjour Hyperapp!
)
{
nom: "h1",
les accessoires: {},
enfants: "Bonjour Hyperapp!"
}
view ()
est appelée chaque fois que l'objet
change. Hyperapp va alors construire un nouvel arbre DOM virtuel en fonction des changements qui se sont produits. Hyperapp s'occupera alors de mettre à jour la page web de la manière la plus efficace en comparant les différences du nouveau DOM virtuel avec l'ancien stocké en mémoire Composants
et
objets de la même manière que la vue. Hello ()
qui accepte un objet en tant que paramètre. Nous extrayons la valeur name
de cet objet en utilisant la déstructuration, avant de retourner un en-tête contenant cette valeur: const Hello = ({name}) =>
Hello {name}
;
const view = (state, actions) => (
)
State
name
: const state = {
nom: "Hyperapp"
}
const view = (state, actions) => (
)
nous pouvons utiliser sa propriété
comme attribut du composant Actions
reste stable. Un nouvel état
est créé en fusionnant les résultats d'une action avec l'état précédent. Cela entraînera l'appel de la fonction view
et la mise à jour du code HTML changeName ()
. Cette fonction accepte un argument appelé name
et renvoie une fonction curry utilisée pour mettre à jour la propriété name
dans l'objet state
avec ce nouveau nom. const actions = {
changeName: nom => état => ({nom: nom})
}
onclick
pour appeler l'action, avec un argument de "Batman". Pour ce faire, mettez à jour la vue view
comme suit: const view = (state, actions) => (
Hyperliste
const {h, app} = hyperapplication;
/ ** @jsx h * /
état const = {
}
const actions = {
}
const view = (état, actions) => (
)
const main = app (état, actions, vue, document.body);
// polices
@import url ("https://fonts.googleapis.com/css?family=Racing+Sans+One");
$ base-fonts: Helvetica Neue, sans-serif;
$ heading-font: Racing Sans One, sans-serif;
// couleurs
$ primary-color: # 00caff;
$ secondary-color: hotpink;
$ bg-color: # 222;
* {
marge: 0;
rembourrage: 0;
taille de boîte: border-box;
}
corps {
rembourrage-dessus: 50px;
arrière-plan: $ bg-color;
couleur: $ primary-color;
affichage: flex;
hauteur: 100vh;
justify-content: centre;
font-family: $ base-polices;
}
h1 {
couleur: $ secondary-color;
& strong {color: $ couleur primaire; }
font-family: $ heading-font;
font-weight: 100;
taille de police: 4.2em;
text-align: centre;
}
une{
couleur: $ primary-color;
}
.fléchir{
affichage: flex;
align-items: top;
marge: 20px 0;
contribution {
bordure: 1px solide $ couleur primaire;
background-color: $ couleur primaire;
taille de police: 1.5em;
font-weight: 200;
largeur: 50vw;
hauteur: 62px;
rembourrage: 15px 20px;
marge: 0;
contour: 0;
& :: - webkit-input-placeholder {
couleur: $ bg-color;
}
& :: - moz-placeholder {
couleur: $ bg-color;
}
& :: - ms-input-placeholder {
couleur: $ bg-color;
}
&: hover, &: focus, &: active {
arrière-plan: $ primary-color;
}
}
bouton {
hauteur: 62px;
taille de police: 1.8em;
rembourrage: 5px 15px;
marge: 0 3px;
}
}
ul # liste {
affichage: flex;
flex-direction: colonne;
rembourrage: 0;
marge: 1.2em;
largeur: 50vw;
li {
taille de police: 1.8em;
alignement vertical: bas;
&.terminé{
couleur: $ secondary-color;
text-decoration: interligne;
bouton{
couleur: $ primary-color;
}
}
bouton {
visibilité: cachée;
arrière-plan: aucun;
border: aucun;
couleur: $ secondary-color;
contour: aucun;
taille de police: 0.8em;
font-weight: 50;
rembourrage-dessus: 0.3em;
marge gauche: 5px;
}
&:flotter{
bouton{
visibilité: visible;
}
}
}
}
bouton {
arrière-plan: $ bg-color;
border-radius: 0px;
bordure: 1px solide $ couleur primaire;
couleur: $ primary-color;
font-weight: 100;
contour: aucun;
rembourrage: 5px;
marge: 0;
&: hover, &: désactivé {
arrière-plan: $ primary-color;
couleur: # 111;
}
&:actif {
description: 2px solide $ couleur primaire;
}
&:concentrer {
bordure: 1px solide $ couleur primaire;
}
}
Initial State and View
état
et une vue simple
il est utile de réfléchir aux données et informations que votre application voudra suivre tout au long de son cycle de vie. Dans le cas de notre liste, nous aurons besoin d'un tableau pour stocker les tâches à faire, ainsi que d'une chaîne représentant tout ce qui est écrit dans le champ de saisie où les tâches réelles sont entrées. Cela ressemblera à ceci: const state = {
articles: [],
contribution: '',
}
view ()
. Pour commencer, nous allons nous concentrer sur le code requis pour ajouter un élément. Ajoutez le code suivant: const view = (state, actions) => (
Hyper liste
const AddItem = ({add, input, value}) => (
qui sera utilisé pour entrer nos to-dos, ainsi qu'un élément
qui sera utilisé pour les ajouter à la liste. Le composant accepte un objet comme un argument, à partir de laquelle nous extrayons trois propriétés:
ajouter
entrée
et valeur
. add ()
sera utilisée pour ajouter un élément à notre liste de choses à faire. Cette fonction est appelée, soit si la touche Enter est pressée (elle a un [KeyCode] de 13) ou si le bouton est cliqué. La fonction
input ()
est utilisée pour mettre à jour la valeur de l'élément courant dans l'état et est appelée chaque fois que le champ de texte reçoit l'entrée de l'utilisateur. Enfin, la propriété
est tout ce que l'utilisateur a tapé dans le champ de saisie. input ()
et add ()
sont des actions , transmis comme accessoires à l'élément :
est extraite de la propriété d'entrée de l'état
. Ainsi, le texte affiché dans le champ de saisie est stocké dans l'état et mis à jour chaque fois qu'une touche est enfoncée input
: const actions = {
entrée: ({valeur}) => ({entrée: valeur})
}
oninput
est déclenché lorsque l'utilisateur tape du texte dans le champ de saisie input ()
s'appelle
dans l'état view ()
et la mise à jour du VDOM Ajout d'une tâche
{
valeur: 'Achetez du lait',
complété: faux,
id: 123456
}
id
. C'est parce que les nœuds VDOM dans Hyperapp nécessitent une clé unique pour les identifier. Nous allons utiliser un horodatage pour cela .
à une chaîne vide. Nous devons ensuite ajouter un nouvel objet au tableau items
. Ceci est fait en utilisant la méthode Array.concat
. Cela fonctionne d'une manière similaire à la méthode Array.push ()
mais il renvoie un nouveau tableau, plutôt que de muter le tableau sur lequel il agit. Rappelez-vous, nous voulons créer un nouvel objet d'état, puis le fusionner avec l'état actuel plutôt que de simplement transformer l'état actuel directement. La propriété valeur
est définie sur la valeur contenue dans state.input
qui représente ce qui a été entré dans le champ de saisie: add: () => state => ({
contribution: '',
éléments: state.items.concat ({
valeur: state.input,
complété: faux,
id: Date.now ()
})
})
add ()
. state = {
input: 'Achetez du lait',
articles: []
}
add ()
qui retournera l'objet d'état suivant: state = {
contribution: '',
articles: [{
value: 'Buy milk',
completed: false,
id: 1521630421067
}]
}
items
dans l'état, mais nous ne pouvons pas les voir! Pour résoudre ce problème, nous devons mettre à jour notre vue. Tout d'abord, nous devons créer un composant pour afficher les éléments de la liste: const ListItem = ({value, id}) =>
id
et key
ont tous deux la même valeur, qui est l'identifiant unique de l'élément. L'attribut
est utilisé en interne par Hyperapp, il n'est donc pas affiché dans le HTML rendu, il est donc utile d'afficher les mêmes informations en utilisant l'attribut id
d'autant plus que cet attribut partage la même condition d'unicité.
state.items
n'inclut pas le code JSX, nous devons donc utiliser Array.map
pour changer chaque objet item du tableau en code JSX, comme ceci: state.items.map (item => ());
state.items
et créer un nouveau tableau contenant ListItem
à la place. Maintenant, nous avons juste besoin d'ajouter cela à la vue. Mettez à jour la fonction view ()
avec le code ci-dessous: const view = (state, actions) => (
Hyper Liste
{state.items.map (item => ())}
ListItem
composants dans une paire de tags afin qu'ils soient affichés comme une liste non ordonnée.
Marquer une tâche comme terminée
terminée
d'une tâche à faire. Un clic sur une tâche non achevée doit mettre à jour sa propriété terminée
vers true
et cliquer sur une tâche terminée devrait retourner sa propriété terminée
à false
] toggle: id => state => ({
éléments: state.items.map (item => (
id === item.id? Object.assign ({}, item, {completed:! Item.completed}): item
))
})
id
qui fait référence à l'identifiant unique de chaque tâche. L'action parcourt ensuite tous des éléments du tableau, en vérifiant si la valeur d'ID fournie correspond à la propriété id
de chaque objet d'élément de liste. Si c'est le cas, cela change la propriété terminée
à l'opposé de ce qu'elle utilise actuellement avec l'opérateur de négation !
. Cette modification est effectuée à l'aide de la méthode Object.assign ()
qui crée un nouvel objet et effectue une fusion superficielle avec l'ancien objet
et les propriétés mises à jour. Rappelez-vous, nous ne mettons jamais à jour les objets dans l'état directement. Au lieu de cela, nous créons une nouvelle version de l'état qui écrase l'état actuel. ListItem
pour qu'il ait un gestionnaire d'événement onclick
qui appellera l'action toggle
que nous venons de créer. Mettez à jour le code du composant ListItem
pour qu'il ressemble à ceci: const ListItem = ({valeur, id, completed, toggle, destroy}) => (
class = {completed && "completed"}
terminé
est vrai. Cela est dû au fait que lorsque vous utilisez &&
la valeur de retour de l'opération sera le deuxième opérande si les deux opérandes sont vrais. Puisque la chaîne "terminée"
est toujours vraie, elle sera renvoyée si le premier opérande - l'argument complété
- est vrai. Cela signifie que, si la tâche est terminée, elle aura la classe "completed" et pourra être stylée en conséquence. view ()
pour ajouter l'argument supplémentaire au composant : const view = (state, actions) => (
Hyper Liste
{
state.items.map (item => (
))
}
Supprimer une tâche
destroy ()
qui supprimera un élément du tableau items
en état. Nous ne pouvons pas le faire en utilisant la méthode Array.slice ()
car il s'agit d'une méthode destructive qui agit sur le tableau d'origine. Au lieu de cela, nous utilisons la méthode filter ()
qui renvoie un nouveau tableau contenant tous les objets élément qui passent une condition spécifiée. Cette condition est que la propriété id
ne correspond pas à l'ID qui a été transmis en tant qu'argument à l'action destroy ()
. En d'autres termes, il renvoie un nouveau tableau qui n'inclut pas l'élément dont nous voulons nous débarrasser. Cette nouvelle liste remplacera l'ancienne lors de la mise à jour de l'état actions
: destroy: id => state => ({items: state. items.filter (item => item.id! == id)})
ListItem
pour ajouter un mécanisme permettant de déclencher cette action. Nous allons le faire en ajoutant un bouton avec un gestionnaire d'événements onclick
: const ListItem = ({valeur, id, terminé, toggle, destroy}) => (
destroy
qui représente l'action que nous voulons utiliser lorsque le bouton est cliqué. Cela est dû au fait que les composants n'ont pas un accès direct à l'objet
dans le même état que la vue, donc la vue doit passer des actions explicitement. actions.destroy
comme argument au composant : const view = (état, actions) => (
Hyper Liste
{state.items.map (item => (
))}
Supprimer toutes les tâches terminées
filter ()
que nous avons utilisée précédemment - renvoyant un tableau qui contient uniquement des objets élément avec une valeur de propriété complétée
de false
. Ajoutez le code suivant à l'objet actions
: clearAllCompleted: ({items}) => ({items: items.filter (item =>! Item.completed)})
onclick
pour appeler cette action au bas de la vue: const view = (state, actions) => (
Hyper Liste
{state.items.map (item => (
))}
C'est Tout, Folks
Source link