【问题标题】:Replace href link with a JS function用 JS 函数替换 href 链接
【发布时间】:2020-07-13 16:13:02
【问题描述】:

在我的 react electron 应用程序中,它使用 API,我接收 JSON 值以将数据显示到组件中。所以例如我有一个Features 组件:

const Features = () => {
  const { title } = useSelector(({ titles }) => titles);
  let string = title.features;
  // the string can contain some html tags. Example bellow:
  // sting = 'This is a string containing a href to <a href="www.google.com">Google</a>';

  string = string.replace(/href="(.*?)"/g, function() {
    return `onClick="${() => shell.openExternal('www.google.com')}"`;
  });

  return (
    <>
      <Heading>Features</Heading>
      <Text content={parsedHTML} />
    </>
  );
};

我想要的是用onClick 替换href 属性并分配Electron 的shell.openExternal() 函数。

string.replace() 回调函数会执行此操作,但是当我单击 &lt;a&gt; 元素时,应用会抛出下一个错误:

error: uncaughtException: 预期 onClick 监听器是 函数,取而代之的是 string 类型的值。

更新

也试过这个逻辑,出现同样的错误:

  global.openInBrowser = openInBrowser; // openInBrowser is basically a function that calls shell.openExternal(url)

  const re = new RegExp('<a([^>]* )href="([^"]+)"', 'g');
  string = string.replace(re, '<a$1href="#" onClick="openInBrowser(\'$2\')"');

这是Sandboxrep 的链接。

我该如何正确地做到这一点?

【问题讨论】:

  • 试试onClick="shell.openExternal('www.google.com')"
  • @LawrenceCherone 我已经试过了,出现同样的错误
  • 那是因为你传递了一个字符串给onClick。只需删除引号,如下所示:'onClick={shell.openExternal('www.google.com')}'
  • @k-wasilewski 是的,我也试过了,也出现同样的错误

标签: javascript reactjs electron


【解决方案1】:

未在 React 元素上设置 onclick 实际上是预期行为。

因为在评估 onclick 字符串时存在 XSS 安全风险。推荐的解决方案是在html-react-parser 中使用replace 选项。

您也可以使用dangerouslySetInnerHTML,这涉及安全风险。

Sandbox Demo

export default function App() {
  let string =
    'This is a string containing html link to <a href="www.google.com">Google</a>';

  const re = new RegExp('<a([^>]* )href="([^"]+)"', "g");
  let replaced = string.replace(re, "<a onclick=\"alert('$2')\"");

  return (
    <div className="App">
      <p dangerouslySetInnerHTML={{__html: replaced}}></p>
      <p>{parse(string, {
        replace: domNode => {
          if (domNode.name === 'a') {
            let href = domNode.attribs.href
            domNode.attribs.onClick = () => { alert(href) }
            delete domNode.attribs.href
          }
        }
      })}</p>
    </div>
  );
}

【讨论】:

  • 你说得对,这是我希望听到的答案,但我自己已经想通了。也许我应该在上面的代码描述中提到,我已经使用这个库来解析 html。
  • 替换方法,来自html-react-parser 成功了
【解决方案2】:

不确定电子的细节,但如果窗口范围内没有可用的 functionName 变量,则在 html 中传递 (function(){functionName()})() 将不起作用。在电子中有一个全球环境,这可能会回答您的问题:

const Features = () => {
  const { title } = useSelector(({ titles }) => titles);
  let string = title.features;
  // the string can contain some html tags. Example bellow:
  // sting = 'This is a string containing a href to <a href="www.google.com">Google</a>';
  
  function runOpen(href){
      shell.openExternal(href)
  }      

  global.runOpen = runOpen;

  string = string.replace(/href="(.*?)"/g, function() {
    return `onClick="runOpen(${'www.google.com'})"`;
  });

  return (
    <>
      <Heading>Features</Heading>
      <Text content={parsedHTML} />
    </>
  );
};

如果没有,您可以使用 onclick="console.log(this)" 之类的东西来找出 onclick 运行的范围,然后在那里分配您的 runOpen 变量。

【讨论】:

  • 我尝试了多次,结果都是一样的,首先 React 抛出一个警告:预期 onClick 侦听器是一个函数,而不是 string 类型的值。然后是错误。
  • onClick 中添加 console.log() 时,由于 React 抛出错误,因此无法到达此代码
  • 抱歉,我假设您使用的是 &lt;div dangerouslySetInnerHTML={parsedHTML} /&gt; 之类的东西,因为您将 html 解析为字符串。但是您可以将 string 变量改为 objectParams 并传递 {onClick: () => shell.openExternal(href)},并在调用元素的位置设置参数值。虽然我很好奇如果不是危险的SetInnerHTML,你如何将元素的字符串应用到你的内容中。
  • 也许我应该在上面的代码描述中提到,我已经使用 html-react-parser 库来解析 html。很抱歉
  • 没听说过这个库,去看看。 tnx.
猜你喜欢
  • 2012-04-25
  • 2018-03-22
  • 2011-03-07
  • 2023-03-18
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
相关资源
最近更新 更多