因为最近很忙,本来打算不断更新博客的。由于时间关系,因此更新较慢。
因为最近有需求,想快速开发一个桌面端应用,最好是采用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