在浏览器中打开来自 Electron 的链接

Posted

技术标签:

【中文标题】在浏览器中打开来自 Electron 的链接【英文标题】:Make a link from Electron open in browser 【发布时间】:2015-10-23 08:04:55 【问题描述】:

是否有任何(简单/内置方式)可以打开一个新浏览器(我的意思是默认操作系统浏览器)窗口以获取来自 Electron 的链接,而不是在您的 Electron 应用程序中访问该链接?

【问题讨论】:

这能回答你的问题吗? How can I force external links from browser-window to open in a default browser from Electron? 【参考方案1】:

我在 Electron v.13 中使用这种方法。

我们拦截用户的导航(window.location)并在默认浏览器中打开网址。

查看文档:https://www.electronjs.org/docs/latest/api/web-contents#event-will-navigate

const  shell  = require('electron');

window.webContents.on('will-navigate', function (e, url) 
    e.preventDefault();
    shell.openExternal(url);
);

【讨论】:

您的答案可以通过提供有关代码的作用以及它如何帮助 OP 的信息来改进。【参考方案2】:

编辑:@Arjun Kava 的回答现在好多了。

这个答案已经很老了,假设你有 jQuery。

const shell = require('electron').shell;
  
// assuming $ is jQuery
$(document).on('click', 'a[href^="http"]', function(event) 
    event.preventDefault();
    shell.openExternal(this.href);
);

【讨论】:

你应该解释一下 $ 的来源。没有它,答案有点不完整。【参考方案3】:

我的代码 sn-p 根据 Electron 版本 ^12.0.0 中的折旧提示

const win = new BrowserWindow();
win.webContents.setWindowOpenHandler(( url ) => 
    // config.fileProtocol is my custom file protocol
    if (url.startsWith(config.fileProtocol)) 
        return  action: 'allow' ;
    
    // open url in a browser and prevent default
    shell.openExternal(url);
    return  action: 'deny' ;
);

【讨论】:

如果有人想知道“拒绝”和“允许”规则。 electronjs.org/docs/api/…【参考方案4】:

要在 Electron 的项目中打开外部链接,您需要模块 Shell (https://www.electronjs.org/docs/api/shell#shell) 和方法 openExternal

但是,如果您正在寻找一种抽象的方式来实现该逻辑,那就是为您的目标属性的自定义目标创建一个处理程序。

const shell = require('electron');

if (document.readyState != "complete") 
    document.addEventListener('DOMContentLoaded', function() 
        init()
    , false);
 else 
    init();


function init()
    handleExternalLinks();
    //other inits



function handleExternalLinks()
    let links = document.getElementsByTagName('a')
    let a,i = 0;
    while (links[i])
        a = links[i]
        //If <a target="_external">, so open using shell.
        if(a.getAttribute('target') == '_external')
            a.addEventListener('click',(ev => 
                ev.preventDefault();
                let url = a.href;
                shell.openExternal(url);
                a.setAttribute('href', '#');
                return false;
            ))
        
        console.log(a,a.getAttribute('external'))
        i++;
    

【讨论】:

有没有办法为openExternal(URL)设置观察者;我想为打开页面的特定 URL 设置观察者,当我得到该 URL 时需要关闭浏览器窗口或选项卡吗? @NikunjBeladiya 在这种情况下,您应该为要在新窗口中打开的每个链接手动设置属性 target="_external"。或者在您的页面标识符中进行某种切换。【参考方案5】:

一些方便的解决方案可以在this gist找到。

通过监听 body,以下解决方案将适用于 &lt;a&gt; 标签,这些标签在 javascript 运行时可能尚不存在,但稍后才会出现在 DOM 中。

luizcarraro 的这个需要 jQuery:

$('body').on('click', 'a', (event) => 
  event.preventDefault();
  require("electron").shell.openExternal(event.target.href);
);

您可以将选择器更改为仅针对某些链接,例如'#messages-view a''a.open-external'

这是一个没有任何库的替代方案(源自zrbecker's):

document.body.addEventListener('click', event => 
  if (event.target.tagName.toLowerCase() === 'a') 
    event.preventDefault();
    require("electron").shell.openExternal(event.target.href);
  
);

更多示例请咨询the gist。

【讨论】:

我使用了以下测试:if (event.target.href &amp;&amp; event.target.href.match(/^https?:\/\//)).【参考方案6】:
mainWindow.webContents.on('new-window', function(e, url) 
  e.preventDefault();
  require('electron').shell.openExternal(url);
);

要求您在锚标记上使用 target="_blank"。

【讨论】:

有什么方法可以在没有 target="_blank" 的情况下处理链接?也许一种方法是将&lt;base target="_blank"&gt; 添加到head ***.com/a/24428525/2129219【参考方案7】:

要在您的实际浏览器(Chrome、Mozilla 等)中运行 Electron 项目,请将其添加到您的脚本中:外部脚本:

aTags = document.getElementsByTagName("a");
for (var i = 0; i < aTags.length; i++) 
     aTags[i].setAttribute("onclick","require('shell').openExternal('" + aTags[i].href + "')");
     aTags[i].href = "#";

【讨论】:

您不需要多个事件侦听器(您可以使用事件委托来处理新创建的元素并提高效率,并且有其他不涉及 DOM 的问题的替代解决方案完全)。您不应使用onclick 属性来定义事件侦听器。您引入了一个安全漏洞,例如&lt;a href="'+alert('exploit!')+'"&gt;exploit&lt;/a&gt; - 你应该改用addEventListener。 (或至少例如 aTags[i].onclick = ()=&gt; require('shell').openExternal(this.href) 很短,但会破坏以这种方式添加的任何现有侦听器)【参考方案8】:

要使所有 Electron 链接在默认操作系统浏览器中从外部打开,您必须向它们添加 onclick 属性并更改 href 属性,使其不会在 Electron 应用程序中加载任何内容。

你可以这样使用:

aTags = document.getElementsByTagName("a");
for (var i = 0; i < aTags.length; i++) 
  aTags[i].setAttribute("onclick","require('shell').openExternal('" + aTags[i].href + "')");
  aTags[i].href = "#";

但是确保整个文档在之前加载否则它将无法工作。 更健壮的实现如下所示:

if (document.readyState != "complete") 
  document.addEventListener('DOMContentLoaded', function() 
    prepareTags()
  , false);
 else 
  prepareTags();


function prepareTags()
  aTags = document.getElementsByTagName("a");
  for (var i = 0; i < aTags.length; i++) 
    aTags[i].setAttribute("onclick","require('shell').openExternal('" + aTags[i].href + "')");
    aTags[i].href = "#";
  
  return false;

请记住,如果您加载外部文件,则必须让它们完全加载后也经历此过程。

【讨论】:

你应该了解事件委托,它只需要一个事件监听器,无需额外代码即可处理新创建的元素,效率更高。您不应该使用onclick 属性来定义事件侦听器;你应该改用addEventListener。您引入了一个安全漏洞,可以使用&lt;a href="'+alert('exploit!')+'"&gt;exploit&lt;/a&gt; 进行演示。 (最后,对于这个问题,还有完全不涉及 DOM 的替代解决方案) @1j01 你设法变得粗鲁和居高临下,实际上没有提供更好的答案。这是一个论坛,如果您有更可靠的解决方案,请回答 OP,以便其他人也可以从知识中受益。 我不是要粗鲁;我说的是认真的。我试图适应评论长度限制,这让我分心了如何以礼貌的方式最好地表达我想说的话(这给人的感觉是礼貌)。也许我应该把它分成多个 cmets...当然,我应该少用“you”语句。 改述:监听所有链接的点击事件的更好方法是event delegation,它只需要一个侦听器,并且无需特殊处理即可处理新创建的元素。此外,您不应使用 onclick 属性。此处代码与数据的串联引入了一个安全漏洞,第三方可能会在该漏洞中执行任意代码。 Here's a demonstration. 改写继续: addEventListener 优于 onclick,因为它允许将多个事件侦听器添加到同一元素,但您也可以使用 element.onclick = function() ... 如果您不必担心听众会被覆盖。【参考方案9】:

你可以简单地使用:

require("shell").openExternal("http://www.google.com")

【讨论】:

这里有更好的答案:***.com/questions/32402327/… 可以在 electron 中打开一个站点并前后导航 @John 这没什么大不了的,但我会从其他 Electron 应用程序中获取提示,看看它们如何处理链接。 Discord 和 Slack 在浏览器(非移动)中打开链接,我认为这是一个很好的先例。 如何通过电子应用打开外部链接,但使用特定选择的浏览器,例如 chrome?我不想更改我的设置,也不想使用资源管理器(我的默认浏览器)打开...@zianwar #help someone ?

以上是关于在浏览器中打开来自 Electron 的链接的主要内容,如果未能解决你的问题,请参考以下文章

Electron构建一个文件浏览器应用

在electron.js中打开文件

如何从浏览器链接或提示打开 nodejs 应用程序

如何让电子应用程序打开以“http://”或“https://”开头的所有链接,并在浏览器中打开target =“_ blank”而不是app

electron和vue的关系

将指向外部 URL 的超文本链接点击重新路由到 Electron 应用程序以外的另一个浏览器