添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

渲染进程加载Electron

方式1

浏览器端无法加载electron,那么,我们可以使用preload预加载将需要的接口暴露出来。

创建一个 preload.js 文件,放在入口文件 main.js 的同级目录下。

1
2
3
global.electron = require('electron');
window.ipcRenderer = require('electron').ipcRenderer;
window.remote = require('electron').remote;

修改 main.js 文件
在入口文件中添加preload配置项,将 preload.js 作为预加载文件。预加载的时候还是可以使用nodejs里的api

1
2
3
4
5
6
7
8
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
preload: __dirname + '/preload.js'
}
});

在组件中如下使用即可。

1
2
3
4
5
6
7
const electron = window.electron;
const remote = window.remote;
console.log(electron)
console.log(remote.dialog)

const {dialog} = window.remote;
dialog.showErrorBox('title', 'content');

方式2

1
2
const { app, dialog } = window.require("electron").remote;
const electron = window.require('electron');

主进程和渲染进程数据共享

主进程

1
2
3
global.sharedObject = {
show_tongji: 0
}
1
global.sharedObject.show_tongji = 1;
1
let show_tongji = global.sharedObject.show_tongji;
1
2
3
const remote = window.require('electron').remote;

remote.getGlobal('sharedObject').show_tongji = 1;
1
let show_tongji = remote.getGlobal('sharedObject').show_tongji;
1
remote.getGlobal('sharedObject').show_tongji = 1;

基本配置

区分开发和生产环境

1
const isDevelopment = !app.isPackaged;

高DPI支持

1
2
3
4
if (process.platform === 'win32') {
app.commandLine.appendSwitch('high-dpi-support', 'true')
app.commandLine.appendSwitch('force-device-scale-factor', '1')
}

禁用硬件加速

非常重要 在一些集成显卡的电脑上,默认开启的硬件加速会导致应用看不到界面。

关闭硬件加速

1
app.disableHardwareAcceleration()

webview

HTML

1
2
3
4
<webview :src="url"
id="myweb"
class="myweb"
disablewebsecurity></webview>
1
2
3
4
5
6
7
8
9
10
11
let isreload = false;
this.url = url;
this.$nextTick(() => {
const webview = document.querySelector('#myweb')
webview.addEventListener('dom-ready', () => {
if (!isreload) {
webview.reloadIgnoringCache()
isreload = true
}
})
})
1
2
3
4
5
.myweb {
width: 100%;
height: 100%;
display: flex;
}

初始化Win

1
2
3
4
5
6
7
8
9
10
11
new BrowserWindow({
width: 1130,
height: 650,
transparent: false,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
webSecurity: false,
contextIsolation: false,
webviewTag: true
})

窗口初始化要开启 webviewTag

样式 display: flex; 保证内部充满

webview 调用其方法要等页面 dom-ready

窗口

窗口透明

1
2
3
4
5
6
7
const { BrowserWindow } = require('electron');
const win = new BrowserWindow({
transparent: true,
frame: false,
backgroundColor: '#00000000'
});
win.show();
  • frame设置为false是为了用无边窗口

  • transparent设置为true是使用窗口的透明效果

  • backgroundColor为一个透明的颜色,是因为BrowserWindow默认的背景颜色是白色,设置透明之后,才能够真正地看到透明的效果。

    如果这个属性不设置会导致在有的电脑上是透明的有的不是,必须要设置。

    如果发现经过上述设置之后,窗口仍然不能透明的话,可能和Windows的设置有关
    在Win7下,需要开启aero功能,在Win10下,需要开启颜色->透明效果

    不显示菜单栏

    1
    2
    3
    4
    5
    const electron = require('electron')
    /*获取electron窗体的菜单栏*/
    const Menu = electron.Menu
    /*隐藏electron创听的菜单栏*/
    Menu.setApplicationMenu(null)

    窗口状态

    1
    2
    3
    4
    5
    6
    const { BrowserWindow } = require('electron');
    const win = new BrowserWindow();
    win.setProgressBar(0.5); // 任务栏中的进度条
    let win = new BrowserWindow()
    win.once('focus', () => win.flashFrame(false))
    win.flashFrame(true) // 窗口闪烁

    窗口显示和隐藏

    窗口显示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if (win && !win.isDestroyed()) {
    if (win.isMinimized()) {
    win.restore()
    }

    if (!win.isVisible()) {
    win.show()
    }

    win.focus();
    } else {
    // 创建窗口
    }
    1
    2
    3
    if (win && !win.isDestroyed()) {
    win.hide();
    }

    窗口托栏图标闪烁

    1
    win.flashFrame(true);

    窗口位置

    1
    2
    3
    4
    5
    6
    7
    8
    const win = window.require("electron").remote.getCurrentWindow();
    const {screen} = window.require("electron").remote;

    let display = screen.getPrimaryDisplay();
    let x = display.bounds.width - 80;
    let y = display.bounds.height - 630 - 44;
    win.setSize(76, 630)
    win.setPosition(x, y)
    1
    win.center();
    1
    2
    win.setContentSize(160, 120);
    win.setSize(160, 120);

    如果设置窗口变小 直接调用 setSize 是不生效的,要调用 setContentSize 修改内部尺寸才能改变窗口大小。

    获取窗口句柄

    1
    2
    3
    4
    const win = window.require("electron").remote.getCurrentWindow();
    let hwnd = win.getNativeWindowHandle();
    let winId = hwnd.readUInt32LE(0);
    console.info("winId", winId);

    禁用右键菜单

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function preventDragbarContext(win) {
    var WM_INITMENU = 0x116;//278
    win.hookWindowMessage(WM_INITMENU, function (e) {
    win.setEnabled(false);
    setTimeout(() => {
    win.setEnabled(true);
    }, 100);
    return true;
    })
    }

    标题栏或者设置css的 -webkit-app-region: drag; 的元素,当接收到右键的时候进行拦截,先设置窗口禁用,然后定时恢复。

    特殊处理

    1
    2
    app.disableDomainBlockingFor3DAPIs();   // 关闭3D api, 提高兼容性
    app.disableHardwareAcceleration(); // 关闭硬件加速, 减少渲染问题

    最大化最小化/显示隐藏/获得焦点

    API

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // 渲染进程获取窗口
    const win = window.require("electron").remote.getCurrentWindow();

    // 返回 Boolean - 判断窗口是否最大化
    win.isMaximized()
    // 最大化
    win.maximize()
    // 取消窗口最大化
    win.unmaximize()

    // 返回 Boolean -判断窗口是否最小化
    win.isMinimized()
    // 最小化
    win.minimize()
    // 将窗口从最小化状态恢复到以前的状态。
    win.restore()

    // 返回 Boolean - 判断窗口是否聚焦
    win.isFocused()
    // 聚焦于窗口
    win.focus()
    // 取消窗口的聚焦
    win.blur()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    if (win && !win.isDestroyed()) {
    if (win.isMinimized()) {
    win.restore()
    }

    if (!win.isVisible()) {
    win.show()
    }

    if (!win.isFocused()) {
    win.focus()
    }
    } else {
    createFun()
    }

    双击最大化问题

    Electron无边框模式下 -webkit-app-region: drag; 双击最大化的问题
    废话不多说 使用以下api即可解决:

    1
    2
    3
    4
    5
    mainWindow.setMenu(null);
    // 设置窗口是否可以由用户手动最大化
    mainWindow.setMaximizable(false);
    // 设置用户是否可以调节窗口尺寸
    mainWindow.setResizable(false);

    或者创建窗口设置属性

    1
    2
    maximizable: false,
    minimizable: false,

    防止窗口加载闪烁

    1
    2
    3
    4
    5
    const { BrowserWindow } = require('electron')
    const win = new BrowserWindow({ show: false })
    win.once('ready-to-show', () => {
    win.show()
    })

    防止透明窗口显示闪烁

    main.js中添加

    1
    app.commandLine.appendSwitch('wm-window-animations-disabled');

    创建无边框窗口

    1
    2
    3
    const { BrowserWindow } = require('electron')
    const win = new BrowserWindow({ width: 800, height: 600, frame: false })
    win.show()

    禁止缩放

    1
    2
    3
    new BrowserWindow({  
    resizable: false
    })

    事件穿透

    点击穿透窗口

    1
    2
    3
    const { BrowserWindow } = require('electron')
    const win = new BrowserWindow()
    win.setIgnoreMouseEvents(true)

    转发

    忽略鼠标消息会使网页无视鼠标移动,这意味着鼠标移动事件不会被发出。 在 Windows 操作系统上,可以使用可选参数将鼠标移动消息转发到网页,从而允许发出诸如 mouseleave 之类的事件:

    1
    2
    3
    4
    5
    6
    7
    8
    const win = require('electron').remote.getCurrentWindow()
    const el = document.getElementById('clickThroughElement')
    el.addEventListener('mouseenter', () => {
    win.setIgnoreMouseEvents(true, { forward: true })
    })
    el.addEventListener('mouseleave', () => {
    win.setIgnoreMouseEvents(false)
    })

    这将使网页在 el 上点击时穿透,在它外面时恢复正常。

    渲染进程关闭窗口

    1
    2
    3
    const remote = require('electron').remote;
    const win = remote.getCurrentWindow();
    win.close();
    1
    2
    const {app} = require('electron').remote;
    app.close();

    窗口 不在任务栏显示

    1
    homeWin.setSkipTaskbar(true)

    true 表示不显示,false 表示显示。

    获取焦点闪烁

    1
    2
    win.once('focus', () => win.flashFrame(false))
    win.flashFrame(true)

    别忘了调用 win.flashFramework(false) 来关闭闪烁。 在上面的示例中, 当窗口进入焦点时会调用它, 但您可能会使用超时或其他一些事件来禁用它。

    点击任务栏不隐藏

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    let homeWin = new BrowserWindow({
    width: 1280,
    height: 768,
    fullscreen: true,
    simpleFullscreen: true,
    minimizable: false,
    frame: false,
    resizable: false,
    transparent: true,
    webPreferences: {
    nodeIntegration: true,
    enableRemoteModule: true,
    webSecurity: false,
    contextIsolation: false,
    },
    });
    homeWin.setFullScreen(true);
    homeWin.setAlwaysOnTop(true, "pop-up-menu");

    只设置 simpleFullscreen: true, homeWin.setAlwaysOnTop(true, "pop-up-menu"); 的话,虽然窗口全屏了,但是一点击任务栏上的图标,界面就隐藏了,所以一定要添加上

    1
    homeWin.setFullScreen(true);

    可能你会说直接隐藏任务栏图标不就行了

    1
    homeWin.setSkipTaskbar(true)

    但是这样配置会导致任务栏会遮挡窗口,就算设置窗口置顶也没用,暂时没找到解决方法。

    可拖拽和不可拖拽

    1
    2
    3
    4
    5
    6
    7
    body{
    -webkit-app-region: drag;
    }

    button {
    -webkit-app-region: no-drag;
    }

    如果窗口设置的可拖拽,那么按钮或需要触发点击的就取消拖拽,否则事件无法触发。

    禁用文本选择

    1
    2
    3
    4
    .titlebar {
    -webkit-user-select: none;
    -webkit-app-region: drag;
    }

    自定义滚动条

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    ::-webkit-scrollbar { /*滚动条整体样式*/
    width: 10px; /*高宽分别对应横竖滚动条的尺寸*/
    height: 1px;
    }

    ::-webkit-scrollbar-thumb { /*滚动条里面小方块*/
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 5px #960200;
    background: #960200;
    }

    ::-webkit-scrollbar-track { /*滚动条里面轨道*/
    -webkit-box-shadow: inset 0 0 5px #EDEDED;
    border-radius: 10px;
    background: #EDEDED;
    }

    取消input选中样式

    1
    outline: none;

    设置checkbox选中背景色

    1
    <input type="checkbox" id="remeberpwd"/> <label for="remeberpwd"
    
    
    
    
        
    >记住密码</label>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    input[type=checkbox]{
    cursor: pointer;
    position: relative;
    width: 15px;
    height: 15px;
    font-size: 14px;
    border-radius: 4px;
    }

    input[type=checkbox]::after{
    position: absolute;
    top: 0;
    color: #ffffff;
    width: 15px;
    height: 15px;
    display: inline-block;
    visibility: visible;
    padding-left: 0;
    text-align: center;
    content: ' ';
    border-radius: 3px
    }

    input[type=checkbox]:checked::after{
    content: "✓";
    font-size: 12px;
    background-color: #33C5B3;
    border-radius: 2px;
    }

    禁止图片拖动

    1
    2
    3
    img {
    -webkit-user-drag: none;
    }

    禁用Console警告信息

    cross-env 是一款跨平台设置和使用环境变量的脚本

    1
    npm install --save-dev cross-env
    1
    cross-env ELECTRON_DISABLE_SECURITY_WARNINGS=true

    比如原来我的启动命令为

    1
    2
    3
    "scripts": {
    "start": "webpack --mode development && electron .",
    }
    1
    2
    3
    "scripts": {
    "start": "webpack --mode development && cross-env ELECTRON_DISABLE_SECURITY_WARNINGS=true electron .",
    }

    隐藏掉这些警告信息,仅仅是个掩耳盗铃的行为,并不值得推荐使用。一定要看看警告是否能解决,不能解决又有强迫症的可以这样做。

    Dev-Tools

    安装本地Dev-Tools插件

    官方文档: https://www.electronjs.org/docs/api/browser-window#browserwindowadddevtoolsextensionpath-deprecated

    插件下载地址

    链接: https://pan.baidu.com/s/19BzaBnZsWZxN_thHHvSYBw
    提取码:psvm

    Electron不同版本的API不一样

    1
    2
    3
    4
    5
    6
    7
    const isDevelopment = !app.isPackaged;
    app.whenReady().then(() => {
    if (isDevelopment && !process.env.IS_TEST) {
    BrowserWindow.addDevToolsExtension(path.resolve(__dirname, "./vue-devtools"))
    }
    createWindow();
    });
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    const isDevelopment = !app.isPackaged;
    app.whenReady().then(() => {
    if (isDevelopment && !process.env.IS_TEST) {
    try {
    // 安装vue-devtools
    const {session} = require("electron");
    const path = require("path");
    session.defaultSession.loadExtension(
    path.resolve(__dirname, "./vue-devtools") //这个是插件目录
    );
    } catch (e) {
    console.error("Vue Devtools failed to install:", e.toString());
    }
    }
    createWindow();
    });

    打开 devtools

    1
    mainWindow.webContents.openDevTools();

    默认状态下,开发者工具的位置是上一次工具打开的位置(左边,右边,下边都有可能。取决于上一次的状态,但不会是分离状态,也没有处于顶部的状态)。

    界面右侧打开

    1
    mainWindow.webContents.openDevTools({mode:'right'});

    界面底部打开

    1
    mainWindow.webContents.openDevTools({mode:'bottom'});

    界面左侧打开

    1
    mainWindow.webContents.openDevTools({mode:'left'});

    分离状态打开

    1
    mainWindow.webContents.openDevTools({mode:'detach'});

    DIV可拖动

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    drag_user_camera() {
    let that = this;
    let user_camera = this.$refs["user_camera"];

    let camera_outer = this.$refs["camera_outer"];
    camera_outer.addEventListener('mousedown', mouseDown, false);

    document.addEventListener('mouseup', mouseUp, false);

    function mouseDown() {
    document.addEventListener('mousemove', sliderMove, false);
    }

    function mouseUp() {
    document.removeEventListener('mousemove', sliderMove, false);
    if (that.camera_big) {
    return
    }
    let myleft = parseInt(user_camera.style.left);
    let mytop = parseInt(user_camera.style.top);
    if (mytop < 0) {
    mytop = 0;
    }
    if (mytop + user_camera.clientHeight > document.body.clientHeight) {
    mytop = document.body.clientHeight - user_camera.clientHeight;
    }

    if (myleft < user_camera.clientWidth / 2) {
    myleft = user_camera.clientWidth / 2;
    }

    if (myleft + user_camera.clientWidth / 2 > document.body.clientWidth) {
    myleft = document.body.clientWidth - user_camera.clientWidth / 2;
    }
    user_camera.style.left = myleft + 'px';
    user_camera.style.top = mytop + 'px';
    }

    function sliderMove(e) {
    if (that.camera_big) {
    return
    }
    user_camera.style.left = e.clientX + 'px';
    user_camera.style.top = e.clientY - (user_camera.clientHeight / 2) + 'px';
    }
    },

    图片置灰

    1
    2
    3
    4
    5
    6
    7
    8
    .userhead.gray {
    -webkit-filter: grayscale(100%);
    -moz-filter: grayscale(100%);
    -ms-filter: grayscale(100%);
    -o-filter: grayscale(100%);
    filter: grayscale(100%);
    filter: gray;
    }

    预处理脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 添加preload.js
    const path = require('path');
    mainWindow = new BrowserWindow({
    webPreferences: {
    preload: path.join(__dirname, 'preload.js'),
    },
    });
    // preload.js的实现
    const {ipcRenderer, remote, clipboard} = require('electron');
    window.addEventListener('DOMContentLoaded', () => {
    const element = document.getElementById('chrome-version');
    if (element) {
    element.innerText = process.versions['chrome'];
    }
    });
  •