2
votes

Conversion de texte brut en lien hypertexte en javascript

J'ai un cas d'utilisation où j'ai besoin d'identifier des numéros de téléphone dans une chaîne et de les convertir en lien cliquable. L'utilisation d'une bibliothèque externe est actuellement hors de portée.

Voici ce que j'ai fait jusqu'à présent:

Chaîne: "Ceci est mon numéro de téléphone - 1234567890" Je peux extraire 1234567890 en tant que numéro de téléphone en utilisant un modèle d'expression régulière.

Je veux maintenant le remplacer dans la chaîne d'origine, voici donc ce que j'ai fait:

This is my phone number - [object Object]

Quand je fais cela, au lieu d'obtenir le numéro de téléphone sous forme de lien hypertexte, ma sortie est comme ceci:

const newString = <a href="#">number</a>

Si je crée ma newString sans guillemets, comme ceci

This is my phone number - <a href="#">1234567890</a>

ma sortie est comme ceci:

const string = "This is my phone number - 1234567890"
const number = "1234567890"
const newString = '<a href="#">' + number + '</a>'
number = number.replace(number, newString);

Comment puis-je en faire un lien cliquable?

p>


6 commentaires

On ne sait pas comment vous obtenez votre sortie. Mettez-vous number dans une valeur de retour JSX quelque part? Veuillez montrer ce code.


Double possible de Comment mettre en évidence les correspondances dans une chaîne avec JSX? < / a>


Alors que le candidat en double se concentre sur la mise en évidence des mots, le concept est exactement le même pour remplacer une partie d'une chaîne et rendre JSX valide sans dangerouslySetInnerHTML .


Copie possible de la chaîne au format HTML dans reactjs


Aussi, peut-être juste const newString = <> Ceci est mon numéro de téléphone - {number} ; ?


Exemple de travail ci-dessous.


3 Réponses :


2
votes

Vous devrez remplacer pour envelopper les numéros de téléphone avec des liens, puis utiliser dangerouslySetInnerHTML à ajouter aux composants React.

Remarque: Il s'appelle dangerouslySetInnerHTML car vous vous ouvrez aux attaques XSS à partir de contenu généré par l'utilisateur. Vous devez nettoyer les chaînes en premier. P >

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>
const Linkify = ({ text, pattern, formatter }) => {
  const arr = getSegments(pattern, text);

  return arr.map(formatter);
};

const text = 'This is my phone number - 1234567890, and his is 34234123142';
const pattern = /\d+/g;
const formatter = ({ text, match }) => match ? <a href={`#${text}`}>{text}</a> : text;

ReactDOM.render(
  <Linkify text={text} pattern={pattern} formatter={formatter} />,
  root
);

function getSegments(rex, str) {
  const segments = [];
  let lastIndex = 0;
  let match;
  rex.lastIndex = 0; // In case there's a dangling previous search
  while (match = rex.exec(str)) {
    if (match.index > lastIndex) {
      segments.push({ text: str.substring(lastIndex, match.index) });
    }
    segments.push({ text: match[0], match: true });
    lastIndex = match.index + match[0].length;
  }
  if (lastIndex < str.length) {
    segments.push({ text: str.substring(lastIndex) });
  }
  return segments;
}

Sans utiliser dangerouslySetInnerHTML , le problème principal est de casser la chaîne en chaînes de liens / non-liens. Cela peut être fait en utilisant le code de cette réponse . J'ai mis à jour le code pour marquer la chaîne comme correspondance, afin que vous puissiez la formater en conséquence.

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>
const Linkify = ({ text, pattern, formatter }) => {
  const __html = text.replace(pattern, formatter);

  return <div dangerouslySetInnerHTML={{ __html }} />;
};

const text = 'This is my phone number - 1234567890';
const pattern = /\d+/g;
const formatter = str => `<a href="#${str}">${str}</a>`;

ReactDOM.render(
  <Linkify text={text} pattern={pattern} formatter={formatter} />,
  root
);


1 commentaires

merci pour l'explication @OriDrori! c'était essentiellement ce que j'essayais de réaliser.



-1
votes

<p class="body">
  This is my phone number - 555-555-5555
</p>
const string = document.querySelector("body");
const text = string.innerText;

const textArr = text.split(" ").map(item => {
  if(item.match(/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im)){
    item = `<a href="tel:${item}">${item}</a>`;
  }
  return item;
});

const newText = textArr.join(" ");

console.log({ newText })

string.innerHtml = newText;


2 commentaires

C'est une question React, manipuler directement le DOM est une mauvaise pratique.


Ahhh. Je n'ai pas vu la balise reactjs. Seulement vu javascript dans le titre.



1
votes

Vous ne voulez pas vraiment définir une "chaîne" sur const newString , j'appellerais cela plus un élément. Vous pouvez le faire comme ceci:

<href={`tel:${number}`}>

numéro est le numéro de téléphone stocké dans une variable appelée numéro .

Ensuite, vous écririez:

<p>My phone number is - {phoneEl}</p>

Je suggérerais aussi

const phoneEl = (
  <a href="#">
    {number}
  </a>
);

si vous vouliez que les gens puissent cliquez sur le lien et composez le numéro.


2 commentaires

C'est la meilleure réponse qui prend en compte les meilleures pratiques de React. Il ne manque que les crochets: href = {`tel: $ {number}`} (voté quand même)


@EmileBergeron ouais, ouais haha, je l'ai réparé. Je ne sais pas pourquoi il a été rejeté sans commentaire: /