JavaScript >> Tutoriel Javascript >  >> Tags >> APP

Pas une autre application à faire :partie 5

Se salir les mains et se mouiller les pieds avec les recommandations de composants Web ouverts... en quelque sorte.

Bienvenue dans "Not Another To-Do App", une revue trop longue de la création de l'une des plus petites applications que chaque développeur finit par écrire à un moment ou à un autre. Si vous êtes ici pour en savoir plus sur une technique spécifique d'écriture d'applications ou si vous avez parcouru une installation précédente, alors vous êtes probablement au bon endroit et devriez continuer à lire ! Si ce n'est pas le cas, il est possible que vous souhaitiez commencer par le début afin que vous puissiez vous aussi connaître toutes les histoires de nos personnages...

Si vous êtes arrivé jusqu'ici, pourquoi arrêter maintenant ?

Faites-en un composant

Ok, bien sûr, celui-ci semble être une évidence, je voulais une interface utilisateur basée sur des composants Web, j'ai choisi le générateur d'open-wc en accord avec son choix de LitElement comme classe de base pour créer des composants Web performants et de haute qualité, donc tout devrait être un composant, n'est-ce pas ?

Mauvais !

Même lorsque vous travaillez dans des composants Web, tout ne doit pas nécessairement être un composant, il suffit parfois d'en faire une partie de modèle (dont nous discuterons plus en détail dans le prochain épisode de "Not Another To-Do App"). De plus, il est tout aussi facile de dire "cela n'a pas besoin d'être un composant" même quand c'est le cas. Il est important de vous contrôler constamment afin de faciliter au maximum la lecture et la compréhension de votre code pour vous. Lorsqu'il s'agit de créer des composants, cela signifie préparer le code à factoriser dans son propre composant, à le factoriser dans le composant parent ou à le factoriser complètement hors d'un projet en tant que dépendance externe, aussi facilement que possible. Je me suis retrouvé là-dedans en pensant au input champ pour la nouvelle interface utilisateur à faire.

À première vue, il s'agit très clairement d'un input élément à côté d'un button élément pour la plupart des gens, non ? Pareil ici. C'est jusqu'à ce que je déconne avec mon application (certains pourraient l'appeler QA [tests d'assurance qualité]) à mi-développement et que je tombe sur ceci :

Bien sûr, c'est juste une application To-Do, pourquoi s'inquiéter que cette partie apparemment petite de l'interface utilisateur ne soit pas à 100 % ? Ma réponse argumentative à cela est:"pourquoi s'inquiéter de quoi que ce soit?" Mais, en réalité, ce n'est qu'une conversation, nous ne parlons que des possibilités. Prenant certaines connaissances que j'avais acquises sur des interfaces utilisateur similaires dans le passé, j'ai commencé à écrire le code que j'ai senti corrigé cette experience. Tourner le input dans un textarea , déposez-le dans un élément conteneur, en donnant un frère pour refléter son contenu, cachez les frères et sœurs derrière lui, et bientôt vous avez un textarea croissant . Ce que vous avez également, c'est beaucoup de code qui n'a rien à voir avec l'écriture d'une tâche à faire à l'intérieur de src/to-do-write.js . Entrez dans l'autocontrôle...

Est-ce directement lié à <to-do-write></to-do-write> ? Non. Cela rendrait-il le flux de code de <to-do-write></to-do-write> plus facile à analyser par son absence? Oui. Est-ce que je l'utilise ailleurs dans mon projet ? Non. Pourrais-je me voir vouloir cela dans un autre projet à l'avenir ? Oui. Il n'y a pas de réponses définitives dans le code, seulement ce qui convient au contexte dans lequel vous travaillez à l'époque, et pour moi, la réponse à ces questions à l'époque était « en faire un composant Web ». Alors, je l'ai fait.

Passant directement à la version finale de sa livraison, la mise en œuvre de ce nouvel élément personnalisé commence dans le src/to-do-write.js code où nous mettons à jour le render() méthode pour inclure mon nouvel élément personnalisé, comme:

<growing-textarea>
    <textarea
        aria-label="Write the next thing you need to get done."
        id="todo"
        name="todo"
        placeholder="What needs to get done?"
    ></textarea>
</growing-textarea>

Cela ressemble beaucoup à un textarea assez normal , droit? Le growing-textarea l'élément personnalisé utilise le modèle de décorateur pour mettre à niveau ce textarea normal avoir des super pouvoirs. (Plug :le Decorator Pattern Plus peut lui en donner encore plus !)

Plongeons dans src/growing-textarea.js découvrir.

class GrowingTextarea extends LitElement {
    static get properties() {
        return {
            value: { type: String }
        };
    }
    constructor() {
        super();
        this.value = '';
        this.setValue = this.setValue.bind(this);
    }
    setValue(e) {
        this.value = e.target.value;
    }
    listenOnSlottedTextarea(e) {
        if (this.textarea) {
            this.textarea.removeEventListener(
                'input',
                this.setValue
            );
        }
        const nodes = e.target.assignedNodes();
        const [textarea] = nodes.filter(
            node => node.tagName === 'TEXTAREA'
        );
        if (!textarea) return;
        this.textarea = textarea;
        this.textarea.addEventListener('input', this.setValue);
    }
    static get styles() {
        return [
            styles,
        ];
    }
    render() {
        return html`
            <slot
                @slotchange=${this.listenOnSlottedTextarea}
            ></slot>
            <span aria-hidden="true">${this.value}</span>
        `;
    }
}

Mais que se passe-t-il vraiment là-bas ?

Tout commence par ceci :

<slot
    @slotchange=${this.listenOnSlottedTextarea}
></slot>

Vérifiez le lit-element écoute d'événement basée sur le slot élément pour le slotchange un événement. Cela signifie qu'à tout moment le contenu de la valeur par défaut slot dans le modèle de growing-textarea changements, ou en d'autres termes :

<growing-textarea>
    <!--
        any changes here that don't have 
        a specific [slot="..."] attribute
    -->
</growing-textarea>

Ce changement déclenche un appel à listenOnSlottedTextarea . Une fois que vous entrez dans cet écouteur, vous avez accès à event.target.assignedNodes() qui vous donnera un tableau des nœuds affectés au slot en question. Il y a un peu de travail administratif en cours là-dedans, mais l'effet net est de pouvoir capturer la valeur du textarea tel qu'il est entré. Cette valeur est ensuite appliquée à un élément miroir qui étend la hauteur du growing-textarea element, dont la hauteur gère maintenant la hauteur du textarea via le CSS comme suit :

:host {
    display: block;
    position: relative;
    min-height: 20px;
    width: 100%;
}
span,
::slotted(textarea) {
    min-height: 20px;
    padding: 2px 6px;
    font-size: 14px;
    line-height: 16px;
    box-sizing: border-box;
}
span {
    border: 1px solid;
    display: block;
    white-space: pre-wrap;
}
::slotted(textarea) {
    position: absolute;
    top: 0;
    width: 100%;
    height: 100%;
    border: 1px solid black;
    resize: none;
    font-family: inherit;
    z-index: 2;
}

De plus, cet élément est maintenant pris en compte dans un format qui facilitera sa publication dans son propre package autonome. Lorsque vous choisissez de faire exactement cela, n'oubliez pas le reste des recommandations open-wc pour rendre votre nouveau package à l'épreuve des balles lors de sa distribution dans vos différents projets, votre équipe ou, espérons-le, la communauté JS dans son ensemble. Une fois que vous avez terminé, faites-moi savoir dans les commentaires ci-dessous le type d'éléments personnalisés que vous avez créés.

Avis de non-responsabilité :non, le assignedNodes n'est pas actuellement disponible pour x-browser, et webcomponents.js n'ajoute pas activement cet événement aux navigateurs non compatibles. En cela, nous ne faisons que décorer le textarea avec le growing-textarea élément personnalisé, ce manque de support ne cassera pas réellement notre application, les utilisateurs de ces navigateurs obtiendront simplement une UX un peu différente de celle des utilisateurs de navigateurs plus modernes. Si vous n'êtes pas à l'aise avec la livraison de la zone de texte croissante via une amélioration progressive, cela pourrait mettre un frein à l'ensemble de l'approche que je viens de décrire. Cependant, vous pouvez appliquer une version compatible x-browser de ce code lorsque vous utilisez FlattenedNodesObserver tel que vendu par la bibliothèque Polymer.js si vous souhaitez opter pour une couverture plus large du navigateur pour cette fonctionnalité. Vous pouvez choisir votre propre aventure sur celui-ci.

Bien que je ne vais pas approfondir la façon dont FlattenedNodesObserver travaille ici, je prévois d'écrire plus en détail bientôt, alors restez à l'écoute.

Le petit jeu

Comme voté par une pluralité de personnes ayant des opinions sur de tels sujets qui sont à la fois obligées de voir mes tweets dans leur fil Twitter et ont eu une minute gratuite la semaine dernière, un article de plus de 9000 mots est un non, non.

C'est donc avec le plus profond respect pour vous, cher lecteur, que j'ai divisé les conversations à venir en une dizaine de sections. Félicitations, vous approchez de la fin du premier ! Si vous vous êtes bien amusé jusqu'à présent, ou si vous faites partie de ces personnes qui donnent à une nouvelle sitcom quelques épisodes pour prendre son envol, voici une liste des autres que vous pouvez ajouter à votre file d'attente Netflix :

  • Pas une autre application de tâches
  • Mise en route
  • Testez tôt, testez souvent
  • Mesurer deux fois, pelucher une fois
  • Faites-en un composant (vous êtes ici)
  • Faites-en une pièce réutilisable
  • Votre composant a-t-il vraiment besoin de le savoir ? (Avez-vous ?)
  • Séparez les choses tôt, souvent et seulement si nécessaire
  • Certaines abstractions ne sont pas (seulement) pour votre application
  • Gestion de données réutilisable et évolutive/Et, au final...
  • Voir l'application en action

Un merci spécial à l'équipe d'Open Web Components pour le grand ensemble d'outils et de recommandations qu'ils ont mis en place pour soutenir la communauté toujours croissante d'ingénieurs et d'entreprises apportant des composants Web de haute qualité dans l'industrie. Visitez-les sur GitHub et créez un problème, soumettez un PR ou créez un dépôt pour participer à l'action !