Electron: 如何从<a>默认操作系统浏览器</a>打开 url

创建于 2015-04-01  ·  26评论  ·  资料来源: electron/electron

最有用的评论

我在 SO 上找到了这个代码片段:

    var shell = require('electron').shell;
    //open links externally by default
    $(document).on('click', 'a[href^="http"]', function(event) {
        event.preventDefault();
        shell.openExternal(this.href);
    });

将它放在我的主索引文件中,据我所知,它似乎可以正常工作,即使对于动态生成的链接也是如此。 我对电子太菜了,不知道这是否有任何我应该注意的缺点。 想法?

所有26条评论

在我的设置中,我尝试了shell.openExternal('http://example.com')shell.openItem('http://example.com')并且都在后台打开了网站。

我最终在 Win32 上使用了child_process.execSync('start http://example.com') ,在 Darwin 上使用child_process.execSync('open http://example.com') ,因此浏览器实际上会弹出并获得焦点。

在 Linux 上,您可以使用 xdg-open:
child_process.execSync('xdg-open http://example.com')

我实际上决定使用node-open 。 如果你不想搞乱逃逸之类的,你应该试一试。

伙计们,但您的解决方案很棒,但我想知道如何拦截尝试打开“ http://someurl.com ”之类的shell.openExternal打开? Service Worker 只允许捕获对同一域中文件的请求。 有能力做到这一点吗? /cc @maxogden @AlicanC

@havenchyk相同的问题,有没有办法告诉电子默认打开外部链接?

如果您的应用仅使用一个窗口,并且您可以保证应用中的每个外部链接都在新窗口中打开(例如通过target="_blank" ),您可以执行以下操作:

webContents.on('new-window', function(event, url){
  event.preventDefault();
  open(url);
});

其中webContents是您的主要 BrowserWindow 的 webContents,而open是一个在您的浏览器中打开 url 的函数(我使用了 AlicanC 推荐的node-open )。

如果在单击 _any_ 链接时触发了一个事件,那就太好了,这样应用程序就可以决定它是否应该在浏览器中打开,但如果存在这样的事件,我还没有找到。

我在 SO 上找到了这个代码片段:

    var shell = require('electron').shell;
    //open links externally by default
    $(document).on('click', 'a[href^="http"]', function(event) {
        event.preventDefault();
        shell.openExternal(this.href);
    });

将它放在我的主索引文件中,据我所知,它似乎可以正常工作,即使对于动态生成的链接也是如此。 我对电子太菜了,不知道这是否有任何我应该注意的缺点。 想法?

我正在使用这段代码:

var handleRedirect = (e, url) => {
  if(url != webContents.getURL()) {
    e.preventDefault()
    require('electron').shell.openExternal(url)
  }
}

webContents.on('will-navigate', handleRedirect)
webContents.on('new-window', handleRedirect)

首先声明一个生成过程

`app.controller('GuideCtrl', ['$scope', ($scope)=>{
const spawn = require('child_process').spawn;

  $scope.openBrowser=(url)=>{
     let exec = spawn('explore', [url], {});
     exec.stdout.on('data', (data)=> {
        console.log('stdout: ' + data)
     });
  }

}])`

在调用方法之前

<a ng-click="openBrowser('https://google.com')">Goto google</a>

shell.openExternal有任何安全问题吗? 例如,如果链接脱离网络,则原始网络数据将传递给shell.openExternal或上述任何其他函数。 shell.openExternal是否确保不会发生任何不好的事情? 我需要过滤模式吗?

基于来自@rubencodes的代码,我使用了:

const shell = require('electron').shell; $('.open-in-browser').click((event) => { event.preventDefault(); shell.openExternal(event.target.href); });

然后,您只需要将“在浏览器中打开”类拖放到要在浏览器中打开的每个元素。

这是一个不需要 JQuery 的,以防其他人正在寻找它。 它会在外部浏览器中自动打开以“http”开头的任何链接。

把它放在你的渲染器进程中:

// Open all links in external browser
let shell = require('electron').shell
document.addEventListener('click', function (event) {
  if (event.target.tagName === 'A' && event.target.href.startsWith('http')) {
    event.preventDefault()
    shell.openExternal(event.target.href)
  }
})

如果您希望所有<a>标签在默认浏览器中打开,请在您的 main.ts 中尝试:

const shell = require('electron').shell;

mainWin.webContents.on('will-navigate', (event, url) => {
  event.preventDefault()
  shell.openExternal(url)
});

这假设您有一个像我这样的单页应用程序。 如果没有,您需要进行一些额外的消毒。

我只想重申,在没有白名单的用户内容中使用它可能是一个巨大的安全漏洞。 我不知道所有各种方案的作用以及它们的输入是什么,但作为一个简单的例子,像这样的链接

 <a href="imessage:hello">click me</a>

将在 macOS 上的 Chrome 和 Safari 中提示用户,但使用上面的代码 Electron 只会打开应用程序。

几乎感觉 Electron 本身应该默认在这里更安全,而不是让每个程序员自己弄清楚如何使其安全。

至少你可能想要类似的东西

function isSafeishURL(url) {
  return url.startsWith('http:') || url.startsWith('https:');
}

mainWin.webContents.on('will-navigate', (event, url) => {
  event.preventDefault();
  if (isSafeishURL(url)) {
    shell.openExternal(url);
  }
});

@greggmanhttps://electronjs.org/docs/api/session#sessetpermissionrequesthandlerhandler 中查看开放的外部权限类型

你可以屏蔽那些👍

嗨,我正在使用 vue.js 并解决了受上述讨论启发的这个问题,如果像我这样使用 vue 的人也有同样的问题,我将我的代码粘贴在这里。

<template>
<div class="board-item" v-for="element in list" :key="element.id">
<span><a class='board-item-a' :href='element.url' target='_blank'>{{element.title}}</a></span>
</div>
</template>

<script>
mounted () {
this.$el.querySelectorAll('.board-item-a').forEach(a => {
a.addEventListener('click', (e) => {
e.preventDefault()
require('electron').shell.openExternal(e.target.href)
})
})
},
</script>

基于@alangrainger - ts 版本的评论:

const {app, shell, BrowserWindow} = require('electron');

...
mainWindow.webContents.on('new-window', function(event, url){
   event.preventDefault();
   shell.openExternal(url);
});

数据 URL 呢?

Angular 7 版本(实时重新加载):

        const openExternalLinksInOSBrowser = (event, url) => {
            if (url.match(/.*localhost.*/gi) === null && (url.startsWith('http:') || url.startsWith('https:'))) {
                event.preventDefault();
                shell.openExternal(url);
            }
        };
        win.webContents.on('new-window', openExternalLinksInOSBrowser);
        win.webContents.on('will-navigate', openExternalLinksInOSBrowser);

url.match(/.*localhost.*/gi) === null部分是必需的,否则当您在 angular 应用程序中更改某些内容时,它会在您的操作系统浏览器中打开新窗口/选项卡,而不是在电子应用程序中重新加载它。

所有方法都可以正常工作,但仅适用于非 root 电子应用程序,我可以使用什么在 root 提升进程的默认操作系统浏览器上打开外部 url?

只是想为其他 Vue.js 用户发布答案。

<template>
  <div>
    <a href="https://google.com" target="_blank" @click.prevent="openExternalBrowser">Google.com Status</a>
  </div>
</template>

<script>
const { remote } = require('electron');

export default {
  name: 'HelloWorld',
  methods: {
    openExternalBrowser(e) {
      remote.shell.openExternal(e.target.href);
    },
  },
};
</script>

只是想为其他 Vue.js 用户发布答案。

<template>
  <div>
    <a href="https://google.com" target="_blank" @click.prevent="openExternalBrowser">Google.com Status</a>
  </div>
</template>

<script>
const { remote } = require('electron');

export default {
  name: 'HelloWorld',
  methods: {
    openExternalBrowser(e) {
      remote.shell.openExternal(e.target.href);
    },
  },
};
</script>

谢谢你。

main.js

app.on('web-contents-created', (e, contents) => {
    contents.on('new-window', (e, url) => {
      e.preventDefault();
      require('open')(url);
    });
    contents.on('will-navigate', (e, url) => {
      if (url !== contents.getURL()) e.preventDefault(), require('open')(url);
    });
});

您需要安装开放包

npm i open --save

只是想为其他 Vue.js 用户发布答案。

@travis5491811这会打开另一个带有正确页面的电子窗口。 这是预期的行为吗?

不,如果正确实施,我的帖子应该回答线程票“如何从默认操作系统浏览器打开 url 我提供的答案在我的应用程序 Electron v5.0.11 、Vue v2.6.10中有效,在多台 Windows 10 和 Linux 桌面机器上进行了生产测试

只是想为其他 Vue.js 用户发布答案。

@travis5491811这会打开另一个带有正确页面的电子窗口。 这是预期的行为吗?

此页面是否有帮助?
0 / 5 - 0 等级