2 votes

React remplace event.target par input

UPDATE Voici quelques démonstrations

contenuDémo éditable - nécessite un double clic pour que H1 devienne éditable

remplacer par la démo d'entrée - adopte event.target mais l'interface utilisateur se met à trembler lorsqu'elle est rendue.


J'ai donc des composants fonctionnels, par exemple :

component1.js

import React from 'react';
const component1 = props => (
<div>
 <h1>Title</h1>
</div>
);
export { component1 };

Ils sont variables. event.target Il peut s'agir de n'importe quel élément de texte, comme un paragraphe, un titre, etc. J'essaie de permettre aux utilisateurs de modifier le contenu en ligne en cliquant dessus, donc je vais passer une fonction editMode à ces composants fonctionnels, qui mettront à jour l'état du parent avec les informations d'édition, disons comme ceci :

<h1 onClick={event => {editMode(event, props.name, props.title, 'title')}}>title</h1>

Cela change l'état local du parent pour avoir toutes les informations nécessaires pour récupérer la valeur de redux, définir une cible, etc. Pour cet exemple, props.name est le nom du composant, props.title est la valeur, et 'title' est la clé de l'objet dans redux.

Donc je vais ajouter quelque chose à mon component1.js et le faire ressembler un peu à ça :

import React from 'react';
const component1 = props => (
    <div>
        {props.editState === 'true' &&
            <EditLayout
                name={props.name}
                target={props.target}
                value={props.value}
                onChange={event => someFunc(event)}
            />
        }
        <h1>Title</h1>
    </div>
    );
export { component1 };

Maintenant, cela fonctionne bien, sauf qu'il n'y a pas d'échelle. EditLayout dans ce cas, retournera simplement une entrée avec une valeur correcte. Ce que je veux qu'il fasse, c'est s'adapter à ce qui est cliqué, obtenir la taille de la police, l'arrière-plan, le rembourrage, la marge, la position. Est-ce que je fais bien les choses ? Chaque fois que j'essaie, je rencontre d'énormes problèmes :

Idée 1 - déménager EditLayout en dehors du composant fonctionnel

Question : positionnement

Je vais donc déplacer EditLayout vers le composant parent qui contient les deux éléments suivants component1.js y EditLayout . Cela me permettra de le manipuler depuis l'intérieur du composant fonctionnel, sans avoir à l'inclure partout. Je vais ensuite récupérer les coordonnées et d'autres informations importantes à partir de event.target comme ça :

const coords = event.target.getBoundingClientRect();
const offsetX = coords.left;
const offsetY = coords.top;
const childHeight = coords.height;
const childWidth = coords.width;
const childClass = event.target.className;

Je vais ensuite envelopper le EditLayout pour retourner un conteneur qui contient une entrée, et appliquer la taille/les coordonnées au conteneur positionné de manière absolue. Cela posera le problème du décalage de l'entrée d'un nombre aléatoire de pixels, en fonction de la taille et de l'emplacement de l'élément d'entrée. event.target .

Idée 2 - transmettre les styles calculés pertinents à EditLayout

Problème : twitching sur le rendu, et je dois ajouter EditLayout pour chaque event.target qu'il y a, ainsi que la condition son' render

Je vais donc saisir tous les styles calculés importants comme ceci :

const computedTarget = window.getComputedStyle(event.target);
const childMargins = computedTarget.marginBottom;
const childPaddings = computedTarget.padding;
const childFontSize = computedTarget.fontSize;
const childTextAlign = computedTarget.textAlign;

Et le transmettre à component1.js et le transmet ensuite à EditLayout à l'intérieur de l'élément component1.js. I'll then condition the event.target à cacher s'il est édité comme ceci :

<h1 className={ props.target === 'title' ? 'd-none' : ''}>Title</h1>

Et conditionner le EditLayout à ne montrer que si c'est nécessaire :

{props.target === 'title' && <EditLayout />}

Dans cet exemple, cliquer sur h1 affichera l'entrée, mais la mise en page elle-même avec twitch sur le rendu. L'entrée aura exactement la même marge et taille de police que le h1, soit event.target mais il apparaîtra plus grand et prolongera la mise en page. Démonstration :

enter image description here

Idée 3 - Utiliser du contenu conditionnelEditable

Problème : Nécessite un double-clic pour être activé, ne fonctionne pas dans Safari, ne me permet pas de présélectionner la valeur.

C'est le plus bizarre de tous. Je pensais que ce serait assez simple, faire quelque chose comme ça dans le composant fonctionnel render :

<h1 contentEditable={props.target === 'title'} onClick={event => props.setTarget(event)}>Title</h1>

Cependant, je dois double-cliquer pour l'activer. Je n'ai aucune idée de la raison pour laquelle, si je joins un journal de console chaque fois que onClick est déclenchée, j'obtiendrai des sorties correctes, ainsi que la valeur cible correcte. J'ai essayé de nombreuses façons, mais il faut simplement double-cliquer. J'ai même essayé de gérer cela à l'intérieur du composant fonctionnel, car la plupart des choses sont gérées par un composant parent, mais cela ne fait aucune différence.

J'ai simplifié à l'extrême les exemples, de sorte qu'il est prudent de supposer/comprendre ce qui suit :

  • Je passe les props de manière correcte, ils ne sont pas indéfinis.
  • J'utilise bootstrap
  • J'utilise des composants stylisés, et EditLayout est un composant stylé qui accepte les props et les transforme en CSS : font-size: ${props => props.fontSize};
  • Les valeurs devraient être correctes, je ne manipule rien de ce que je reçois en retour de l'ordinateur. getComputedStyle() o getBoundingClientRect()
  • Je tiens à ce que mes composants fonctionnels restent fonctionnels et faciles à utiliser. ajouter. Les composants fonctionnels, dans ce cas, sont de simples structures HTML, et j'aimerais qu'elles restent aussi simples que possible.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X