javascript React:替换文本中的链接

lxkprmvk  于 2022-12-17  发布在  Java
关注(0)|答案(9)|浏览(228)

用React替换字符串中的url并将其呈现为链接的正确方法是什么?
说我有一串:'hello http://google.com world',我希望它渲染为:hello <a href="http://google.com">http://google.com</a> world

5vf7fwbs

5vf7fwbs1#

好吧,我是这么做的。

class A extends React.Component {
  renderText() {
    let parts = this.props.text.split(re) // re is a matching regular expression
    for (let i = 1; i < parts.length; i += 2) {
      parts[i] = <a key={'link' + i} href={parts[i]}>{parts[i]}</a>
    }
    return parts
  }
  render() {
    let text = this.renderText()
    return (
      <div className="some_text_class">{text}</div>
    )
  }
}
ymzxtsji

ymzxtsji2#

我对这里的每一个答案都有疑问,所以我不得不自己写:

// use whatever you want here
const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;

const renderText = txt =>
  txt
    .split(" ")
    .map(part =>
      URL_REGEX.test(part) ? <a href={part}>{part} </a> : part + " "
    );
gfttwv5a

gfttwv5a3#

有NPM模块可以处理这个问题。

第一次(第一次)

<Linkify>
  <div>react-linkify <span>(tasti.github.io/react-linkify/)</span></div>
    <div>React component to parse links (urls, emails, etc.) in text into clickable links</div>
  See examples at tasti.github.io/react-linkify/.
    <footer>Contact: tasti@zakarie.com</footer>
</Linkify>

在撰写本文时,当前版本是1.0.0-alpha。它需要React 16。repo有14个开放票证和17个开放PR。所以这并不好。
版本0.2.2允许更早的版本,但没有链接文本装饰等。

第一个e五个f一x(第一个e六个f一x)

如果你使用的是原生应用(即手机应用),它看起来是两个选项中较好的一个。代码示例:

<Hyperlink linkDefault={ true }>
  <Text style={ { fontSize: 15 } }>
    This text will be parsed to check for clickable strings like https://github.com/obipawan/hyperlink and made clickable.
  </Text>
</Hyperlink>

<Hyperlink onLongPress={ (url, text) => alert(url + ", " + text) }>
  <Text style={ { fontSize: 15 } }>
    This text will be parsed to check for clickable strings like https://github.com/obipawan/hyperlink and made clickable for long click.
  </Text>
</Hyperlink>

<Hyperlink
  linkDefault
  injectViewProps={ url => ({
        testID: url === 'http://link.com' ? 'id1' : 'id2' ,
        style: url === 'https://link.com' ? { color: 'red' } : { color: 'blue' },
        //any other props you wish to pass to the component
  }) }
>
  <Text>You can pass props to clickable components matched by url.
    <Text>This url looks red https://link.com
  </Text> and this url looks blue https://link2.com </Text>
</Hyperlink>

参考文献

gmxoilav

gmxoilav4#

试试这个库,它完全符合您的需要:https://www.npmjs.com/package/react-process-string
下面是一个例子:

const processString = require('react-process-string');

let config = [{
    regex: /(http|https):\/\/(\S+)\.([a-z]{2,}?)(.*?)( |\,|$|\.)/gim,
    fn: (key, result) => <span key={key}>
                             <a target="_blank" href={`${result[1]}://${result[2]}.${result[3]}${result[4]}`}>{result[2]}.{result[3]}{result[4]}</a>{result[5]}
                         </span>
}, {
    regex: /(\S+)\.([a-z]{2,}?)(.*?)( |\,|$|\.)/gim,
    fn: (key, result) => <span key={key}>
                             <a target="_blank" href={`http://${result[1]}.${result[2]}${result[3]}`}>{result[1]}.{result[2]}{result[3]}</a>{result[4]}
                         </span>
}];

let stringWithLinks = "Watch this on youtube.com";
let processed = processString(config)(stringWithLinks);

return (
    <div>Hello world! {processed}</div>
);

这将替换带有或不带有“http://”协议的所有链接。如果只想替换带有协议的链接,请从配置数组中删除第二个对象。

dba5bblo

dba5bblo5#

首先将<a>标记添加到字符串:

function httpHtml(content) {
  const reg = /(http:\/\/|https:\/\/)((\w|=|\?|\.|\/|&|-)+)/g;
  return content.replace(reg, "<a href='$1$2'>$1$2</a>");
}

console.log(httpHtml('hello http://google.com world'))
// => hello <a href="http://google.com">http://google.com</a> world

然后在react中将字符串呈现为html:

function MyComponent() {
  return <div dangerouslySetInnerHTML={{
    __html: httpHtml('hello http://google.com world')
  }} />;
}
ego6inou

ego6inou6#

我写了一个简短的函数来完成它:

const RE_URL = /\w+:\/\/\S+/g;

function linkify(str) {
  let match;
  const results = [];
  let lastIndex = 0;
  while (match = RE_URL.exec(str)) {
    const link = match[0];
    if (lastIndex !== match.index) {
      const text = str.substring(lastIndex, match.index);
      results.push(
        <span key={results.length}>{text}</span>,
      );
    }
    results.push(
      <a key={results.length} href={link} target="_blank">{link}</a>
    );
    lastIndex = match.index + link.length;
  }
  if (results.length === 0) {
    return str;
  }
  if (lastIndex !== str.length) {
    results.push(
      <span key={results.length}>{str.substring(lastIndex)}</span>,
    );
  }
  return results;
}
bhmjp9jg

bhmjp9jg7#

迟到了,但这里有一个稍微修改的版本:

export const linkRenderer = (string: string):ReactNode => {
    const linkExp = /^https?:\/\/[a-z0-9_./-]*$/i
    return <>{
        string.split(/(https?:\/\/[a-z0-9_./-]*)/gi).map((part, k) => <React.Fragment key={k}>
            {part.match(linkExp) ? <a
                href={part}
                onFocus={(e) => { e.stopPropagation() }}
                target="_blank"
                rel="noreferrer"
            >{part}</a>
            : part}
        </React.Fragment>)
    }</>
}

有趣的事情要注意:

  • 它不会在空格或空白处拆分,因此保留现有空格
  • 它只分割链接不是每个单词的部分,从而创建更少的组块
  • 传递给split的regexp必须有捕获括号,如果你想让你的链接成为结果数组的一部分。
  • 在较旧浏览器上,出于安全原因,需要noreferrer属性,且目标为空

希望这能有所帮助。

bpzcxfmw

bpzcxfmw8#

根据OP自己的回答,我想出了一句俏皮话:

{text
  .split(/[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi)
  .map((part, index) => index % 2 === 0 ? part : <a href={part} target="_blank">{part}</a>
}
siv3szwd

siv3szwd9#

对我来说,我是这样解决的

const ActiveProblem = () => {
  const { activeProblem } = useProblems();
  const id = new Date().toString();
  const match = activeProblem.replace(
    urlPattern,
    (matched) => id + matched + id
  );

  return (
      <Typography align="center" variant="body1" color="white">
        {match.split(id).map((str, idx) => {
          if (str.match(urlPattern))
            return (
              <Box component="a" href={str} key={id + idx}>
                {str}
              </Box>
            );
          return str;
        })}
      </Typography>
  );
};

我正在使用带有React的材质UI

相关问题