最全最新方法:Electron开发中设置a标签的href跳转默认浏览器打开链接

因为最近很忙,本来打算不断更新博客的。由于时间关系,因此更新较慢。

背景

因为最近有需求,想快速开发一个桌面端应用,最好是采用H5+JS+CSS3进行开发,这样效率最高。但是要知道,H5来开发桌面端,由于浏览器安全策略问题,是不可能直接给你调用本地系统API的,因此也出现了很多打包框架,国外免费的有Electron(Github团队开发和维护)、NW.js(NodeWebkit.js)及Nativefier(不太推荐)。国内有付费的打包软件,有钱的大佬可以用,比较省心,底层原理还是封装了Electron。

这里我选用的是Electron。虽然NW.js和Nativefier都可以跨平台打包,但是你会才到无数坑。各有优缺点吧,我个人比较喜欢前者。

但是我相信大家在用前端技术做桌面开发的过程中,最大的痛苦就是浏览器的跨域问题、同源问题及其他安全性问题,还有对系统原生API支持力度不够。这里我就遇到了这样一个问题:

在页面中的标签里的href属性,点击以后还是在Electron内置的浏览器(Chrome V8引擎)中跳转并打开多个页面。而我想实现的是,点击链接或者按钮,会自动跳转到系统默认浏览器中。

推荐方法

我在国内网站上查阅了各种教程资料,只能感慨:1.治标不治本,思路不算好;2.很多方法已经过时了。经过我查阅了国外大量文献和教程,最终找到一种合适的办法。这里推荐第一种

1.前提是你的链接需要添加target="_blank"属性才行;

2.然后在main.js主程序中添加shell请求,如下:

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

3.其次在function createWindow()函数中新增一个函数:

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

原来的文件长这样:

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

function createWindow() {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 1600,
    height: 1000,
    ...
    title: "xxx",
    webPreferences: {
      ...
      preload: path.join(__dirname, 'preload.js')
    }
  })
    ...
  // and load the index.html of the app.
  mainWindow.webContents.openDevTools();
  mainWindow.loadFile('index.html')

修改后的文件长这样(注意观察文件的不同):

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

function createWindow() {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 1600,
    height: 1000,
    xxx
    title: "xxx",
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })
  mainWindow.webContents.on('new-window', function(e, url) {
    e.preventDefault();
    require('electron').shell.openExternal(url);
  })
    ...
  // and load the index.html of the app.
  mainWindow.webContents.openDevTools();
  mainWindow.loadFile('index.html')

然后你的链接就可以愉快的跳转到电脑的默认浏览器啦~

其他方法

其他方法我就不多说了,简单描述一下,不同需求可能用到的方法不一样。

方法一

您可以简单地使用:

//老外力荐的方法
require("shell").openExternal("http://www.google.com")

方法二

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

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

方法三

代码片段根据 Electron 版本 v12.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' };
});

方法四

要使所有 Electron 链接在默认 OS 浏览器中从外部打开,您必须向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;
}

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

方法五

通过侦听主体,以下解决方案将适用于JavaScript 运行时可能尚不存在但仅在稍后出现在 DOM 中的标签。

这个需要 jQuery:

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

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

这是一个没有任何库的替代方案:

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

方法六

我将此方法与 Electron v.13 一起使用。

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

请参阅文档: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);
});

方法七

关于tsx语法(Electron):

import { shell } from "electron";
shell.openExternal("http://www.google.com")

方法八

要在 Electron 的项目中打开外部链接,您需要模块 Shell ( shell | Electron ) 和方法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 , 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++;
    }
}

方法九

要在您的实际浏览器(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 = "#";
}

 最后BB两句,全球Internet YYDS,当我们找不到好的办法的时候,学会去外面看看。

所有方法均来自 stackoverflow.com 或 stackexchange.com,在cc by-sa 2.5、cc by-sa 3.0和cc by-sa 4.0下获得许可


版权声明:本文为CSDN博主「InetGeek」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34532102/article/details/125776033

 

你可能感兴趣的:(electron,javascript,软件工程)