我的Electron个人学习笔记

文章目录

  • Electron简单了解
    • 第一个窗口程序
    • 引入js执行读txt
    • Remote模块
  • Electron快速上手
    • 五分钟快速上手
    • 自动刷新页面
    • 主进程和渲染进程
    • 自定义原生菜单
    • 自定义顶部菜单
    • 点击菜单创建新窗口
    • a标签跳转浏览器
    • 打开对话框读取文件
      • 读取文件
      • 保存文件
    • 定义快捷键
      • 主线程定义
      • 渲染进程定义
    • 渲染进程和主线程通讯
    • 断网提醒
    • 打包
      • 附录
    • electron结合框架开发
    • 直接使用模板创建electron-vue

Electron简单了解

首先npm init -y

然后项目目录下:

npm install electron --save-dev

npm i -D electron@latest


npx electron -v

查看是否安装成功!

或者

./node_modules/.bin/electron -v


使用./node_modules/.bin/electron可查看软件界面

如果出现此错误:./node_modules/.bin/electron : 无法加载文件 E:\Project\electron\node_modules.bin\electro
n.ps1,因为在此系统上禁止运行脚本。

管理员CMD执行此命令

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned


不要全局安装

npm install electron -S

第一个窗口程序

准备一个html文件

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <h1>Hello World!h1>
body>
html>

写main.js

var electron = require('electron')

//引用app
var app = electron.app
//窗口引用
var BrowserWindow = electron.BrowserWindow

var mainWindow = null 
//声明要打开的主窗口

app.on('ready',()=>{
    mainWindow = new BrowserWindow({
        width:600,
        height:600
    })
    mainWindow.loadFile('index.html')
    mainWindow.on('closed',()=>{
        mainWindow = null
    })
})

此时终端执行命令:

npm init --yes

发现帮我们写好了package.json

此时执行electron .执行程序

执行成功!

我的Electron个人学习笔记_第1张图片


引入js执行读txt

在目录下新建info.txt

写入内容

新建render文件夹

在文件夹下新建index.js文件

修改html内容

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <button id="btn">内容button>
    <div id="info">

    div>
    <script src="./render/index.js">script>

body>
html>

修改main.js

app.on(‘ready’,()=>{})

webPreferences:{
            nodeIntegration:true,
            contextIsolation:false 
        }
var electron = require('electron')

//引用app
var app = electron.app
//窗口引用
var BrowserWindow = electron.BrowserWindow

var mainWindow = null 
//声明要打开的主窗口

app.on('ready',()=>{
    mainWindow = new BrowserWindow({
        width:600,
        height:600,
        webPreferences:{
            nodeIntegration:true,
            contextIsolation:false 
        }
    })
    mainWindow.loadFile('index.html')
    mainWindow.on('closed',()=>{
        mainWindow = null
    })
})

此时我们写index.js文件


var fs = require('fs')
window.onload= function(){
    var btn = this.document.querySelector('#btn')
    var info = this.document.querySelector('#info')
    btn.onclick = function(){
        fs.readFile("info.txt",(err,data)=>{
            info.innerHTML = data
        })
    }
}

目录结构:

我的Electron个人学习笔记_第2张图片

控制台输入

electron .

测试

点击按钮

我的Electron个人学习笔记_第3张图片

成功渲染出内容,执行成功!


Remote模块

新打开窗口,两个窗口不能通信

现已移除需要新安装

npm install --save @electron/remote

main.js


var electron = require('electron')

//引用app
var app = electron.app
//窗口引用
var BrowserWindow = electron.BrowserWindow

var mainWindow = null 
//声明要打开的主窗口

app.on('ready',()=>{
    mainWindow = new BrowserWindow({
        width:600,
        height:600,
        webPreferences:{
            nodeIntegration:true,
            contextIsolation:false,
            enableRemoteModule:true
        }
    })
    require('@electron/remote/main').initialize()
    require('@electron/remote/main').enable(mainWindow.webContents)
    mainWindow.loadFile('demo.html')
    mainWindow.on('closed',()=>{
        mainWindow = null
    })
})

demo.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <button id="btn">打开新窗口button>
    <script src="./render/demo.js">script>
body>
html>

demo.js

const btn = this.document.querySelector('#btn')

const {BrowserWindow} = require('@electron/remote')

window.onload = function(){
    btn.onclick = ()=>{
        newWin = new BrowserWindow({
            width:200,
            height: 300,
        })
        newWin.loadFile('new.html')
        newWin.on('closed',()=>{
            newWin = null
        })
    }
}

new.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body background="red">
    <h1>我是测试弹出窗口h1>
body>
html>

测试打开新窗口成功!!!

我的Electron个人学习笔记_第4张图片


Electron快速上手

跨平台桌面应用程序!

简单!!

可以使用纯JavaScript调用丰富的原生APIs来创建桌面应用。

专注于桌面应用。

五分钟快速上手

安装

初始化package.json文件

npm init -y

安装electron

cnpm i electron -S

package.json

{
  "name": "electron",
  "version": "1.0.0",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {},
  "devDependencies": {
    "@electron/remote": "^2.0.7"
  }
}

我们加入配置项

注意覆盖,完整json文件

{
  "name": "ele",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "dependencies": {
    "electron": "^17.1.2",
    "electron-reloader": "^1.2.3"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "electron": "electron .",
    "watch": "watchify app/appEntry.js -t babelify -o public/js/bundle.js --debug --verbose",
    "package": "electron-packager ./ DemoApps --overwrite --app-version=1.0.0 --platform=win32 --arch=all --out=../DemoApps --version=1.2.1 --icon=./public/img/app-icon.icns"
  },
  "devDependencies": {
    "babel": "^6.5.2",
    "babel-plugin-transform-es2015-spread": "^6.8.0",
    "babel-plugin-transform-object-rest-spread": "^6.8.0",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.5.0",
    "babelify": "^7.3.0",
    "browserify": "^13.0.1",
    "electron-packager": "^7.0.3",
    "electron-reload": "^1.0.0",
    "watchify": "^3.7.0"
  }
}

npm run electron

自动刷新页面

安装插件:

npm install --save-dev electron-reloader

引入插件

热加载

main.js

const reloader = require('electron-reloader')
reloader(module)

主进程和渲染进程

运行package.json的main脚本的进程是主进程

每个Electron中的web页面运行在它的渲染进程的进程中

ctrl+shift+i打开渲染进程调试

或者

main.js

mianWindow.webContents.openDevTools()

打开调试工具


自定义原生菜单

文档地址:

https://www.electronjs.org/zh/docs/latest/api/menu

main.js

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


app.on('ready',()=>{
    const mainWindow = new BrowserWindow({
        width:600,
        height:600,
        webPreferences:{
            nodeIntegration:true,
        }
    })

    mainWindow.loadFile('./src/index.html')
//定义菜单模板
    const template = [
        {
            label:'文件',
            submenu:[
                {
                    label:'新建项目'
                }
            ]
        },
        {
            label:'关于'
        }
    ]
    //编译模板
    const menu =  Menu.buildFromTemplate(template)
    //设置菜单
    Menu.setApplicationMenu(menu)
})

Menu.setApplicationMenu(menu)

定义点击事件

可以抽离出来

menu.js

const {BrowserWindow,Menu} = require('electron')
//定义菜单模板
const template = [
    {
        label:'文件',
        submenu:[
            {
                label:'新建项目',
                click(){
                    new  BrowserWindow({
                        width:200,
                        height:200,
                    })
                }
            }
        ]
    },
    {
        label:'关于'
    }
]
//编译模板
const menu =  Menu.buildFromTemplate(template)
//设置菜单
Menu.setApplicationMenu(menu)

main.js引入

require('./menu.js')

自定义顶部菜单

可以使用无边框

main.js

我的Electron个人学习笔记_第5张图片

使用css样式自定义菜单div拖拽

我的Electron个人学习笔记_第6张图片

点击菜单创建新窗口

main.js

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


app.on('ready',()=>{
    const mainWindow = new BrowserWindow({
        width:600,
        height:600,
        frame:false,
        webPreferences:{
            nodeIntegration:true,
            contextIsolation:false,
            enableRemoteModule:true
        },
        
    })
    require('@electron/remote/main').initialize()
    require('@electron/remote/main').enable(mainWindow.webContents)
    mainWindow.loadFile('./src/index.html')

menu.js

const {BrowserWindow,Menu} = require('electron')
//定义菜单模板
const template = [
    {
        label:'文件',
        submenu:[
            {
                label:'新建项目',
                click(){
                    new  BrowserWindow({
                        width:200,
                        height:200,
                    })
                }
            }
        ]
    },
    {
        label:'关于'
    }
]
//编译模板
const menu =  Menu.buildFromTemplate(template)
//设置菜单
Menu.setApplicationMenu(menu)

index,js

const {BrowserWindow} = require('@electron/remote')

const newWindow = document.querySelector('.new-window')

newWindow.onclick = function(){
    new BrowserWindow({
        width:200,
        height: 200
    })
}

index.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <link rel="stylesheet" href="./index.css"/>
head>
<body>
    <ul class="custom-menu">
        <li class="new-window">新建li>
        <li>关于li>
    ul>
    <h1>Helloh1>
    <script src="./index.js">script>
body>
html>

index.css

* {
    margin: 0;
    padding: 0;
}

.custom-menu {
    height: 80px;
    width: 100%;
    background: orange;
    -webkit-app-region:drag;
}
ul {
    list-style: none;
}
.custom-menu li{
    float: left;
    width: 60px;
    line-height: 80px;
    text-align: center;
    margin-left: 20px;
    -webkit-app-region: no-drag;
}

拖拽样式会影响弹出新窗口或者点击事件等功能

此时设置style为-webkit-app-region: no-drag;即可!!!


a标签跳转浏览器

shell是两种进程都可用的模块

不需要通过remote

html中写a标签

index.js

const {shell} = require('electron')

const allA = document.querySelectorAll('a')

allA.forEach(item => {
    item.onclick = function(e){
        e.preventDefault()
        //阻止默认行为
        shell.openExternal(item.href)
    }
})

打开对话框读取文件

读取文件

    <button onclick="openFile()" >打开文件button>

index.js

引入fs模块读取

const fs  = require('fs')

打开文件

//打开文件
const textareaEl = document.querySelector('textarea')
function openFile(){
    const res =  dialog.showOpenDialogSync({
        title:'读取文件',
        buttonLabel:'读取',
        filters: [
              { name: 'Custom File Type', extensions: ['js'] },
              { name: 'All Files', extensions: ['*'] }
        ]
    })
    console.log(res[0])
    const fileContent =  fs.readFileSync(res[0]).toString()
    console.log(fileContent)

    textareaEl.value = fileContent
}

保存文件

<button onclick="saveFile()" >保存文件button>
    
<textarea id="tex2">textarea>

保存文件!!!

//打开文件
const textareaEl2 = document.querySelector('#tex2')
//保存文件
function  saveFile(){
    //返回值是路径
    const res =  dialog.showSaveDialogSync({
            title:'保存文件',
            buttonLabel:'保存',
            filters: [
                  { name: 'Custom File Type', extensions: ['ts'] },
                  { name: 'All Files', extensions: ['*'] }
            ]
    })
    //通过node写文件
    fs.writeFileSync(res,textareaEl2.value)
}

定义快捷键

主线程定义

导入模块globalShortcut定义快捷键

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

注册快捷键

模块使用:

 globalShortcut.register('CommandOrcontrol+X',()=>{
        console.log("按下了ctrl+x");
    })
    globalShortcut.register('CommandOrcontrol+M',()=>{
        mainWindow.maximize()
    })
    globalShortcut.register('CommandOrcontrol+T',()=>{
        mainWindow.unmaximize()
    })
    globalShortcut.register('CommandOrcontrol+H',()=>{
        mainWindow.close()
    })

完整代码:

app.on('ready',()=>{
    const mainWindow = new BrowserWindow({
        width:600,
        height:600,
        // frame:false,
        webPreferences:{
            nodeIntegration:true,
            contextIsolation:false,
            enableRemoteModule:true
        },
        
    })
    require('@electron/remote/main').initialize()
    require('@electron/remote/main').enable(mainWindow.webContents)
    mainWindow.loadFile('./src/index.html')
//定义菜单模板
    require('./menu.js')
    mainWindow.webContents.openDevTools()

    globalShortcut.register('CommandOrcontrol+X',()=>{
        console.log("按下了ctrl+x");
    })
    globalShortcut.register('CommandOrcontrol+M',()=>{
        mainWindow.maximize()
        //最大化
    })
    globalShortcut.register('CommandOrcontrol+T',()=>{
        mainWindow.unmaximize()
        //恢复正常
    })
    globalShortcut.register('CommandOrcontrol+H',()=>{
        mainWindow.close()
    })
})

渲染进程定义

和主进程相似

const {BrowserWindow,dialog,globalShortcut} = require('@electron/remote')

渲染进程和主线程通讯

定义一个点击事件

渲染进程发送给主进程

const {shell,ipcRenderer} = require('electron')
const maxwindow = function(){
    console.log("窗口最大化")
    ipcRenderer.send('max-window')
}

主进程接收const {shell,ipcRenderer} = require(‘electron’):

	const {app,BrowserWindow,globalShortcut, ipcMain} = 	require('electron')   
	//定义自定义事件
    ipcMain.on('max-window',()=>{
        mainWindow.maximize()
    })

通讯传参

index.js

let windowSize = 'unmax-window'

const maxwindow = function(){
    windowSize = windowSize == 'max-window'?'unmax-window':'max-window'
    ipcRenderer.send('max-window',windowSize)
}

主进程获取数据

 //定义自定义事件
    ipcMain.on('max-window',(event,arg)=>{
        if(arg === 'max-window'){
           return mainWindow.maximize()
        }else{
           return mainWindow.unmaximize()
        }
        
    })

断网提醒

我的Electron个人学习笔记_第7张图片

打包

使用electron-packager (十分不推荐)

npm install [email protected] -g

npm install electron-packager --save-dev

测试失败,不推荐使用此方式

package.json文件更改

"package": "electron-packager ./ DemoApps --overwrite --app-version=1.0.0 --platform=win32 --arch=all --out=../DemoApps --version=1.2.1 --icon=./public/img/app-icon.icns"

此时

npm run package即可打包

使用electron-builder(推荐)

npm install electron-builder

修改package.json文件

增加字段

"build": {

   "appId": "com.fuck.app",
    
  "productName":"软件名",
  "win": {
    
    "icon": "./icon.ico",
    "target": [
    
    "nsis"
    
  ]
    
  },
    
  "nsis": {
    
  "oneClick": false,
    
  "perMachine": true,
    
  "allowToChangeInstallationDirectory": true
    
  }
    
   },
   "electronDownload":{

    "mirror":"https://npm.taobao.org/mirrors/electron/"
//配置下载加速镜像
  },

"scripts"内增加运行脚本

"build": "electron-builder"

打包成功!!

附录

"build": {
    "productName":"xxxx",//项目名 这也是生成的exe文件的前缀名
    "appId": "com.leon.xxxxx",//包名  
    "copyright":"xxxx",//版权  信息
    "directories": { // 输出文件夹
      "output": "build"
    }, 
    "nsis": {
      "oneClick": false, // 是否一键安装
      "allowElevation": true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
      "allowToChangeInstallationDirectory": true, // 允许修改安装目录
      "installerIcon": "./build/icons/aaa.ico",// 安装图标
      "uninstallerIcon": "./build/icons/bbb.ico",//卸载图标
      "installerHeaderIcon": "./build/icons/aaa.ico", // 安装时头部图标
      "createDesktopShortcut": true, // 创建桌面图标
      "createStartMenuShortcut": true,// 创建开始菜单图标
      "shortcutName": "xxxx", // 图标名称
      "include": "build/script/installer.nsh", // 包含的自定义nsis脚本
    },
    "publish": [
      {
        "provider": "generic", // 服务器提供商 也可以是GitHub等等
        "url": "http://xxxxx/" // 服务器地址
      }
    ],
    "files": [
      "dist/electron/**/*"
    ],
    "dmg": {
      "contents": [
        {
          "x": 410,
          "y": 150,
          "type": "link",
          "path": "/Applications"
        },
        {
          "x": 130,
          "y": 150,
          "type": "file"
        }
      ]
    },
    "mac": {
      "icon": "build/icons/icon.icns"
    },
    "win": {
      "icon": "build/icons/aims.ico",
      "target": [
        {
          "target": "nsis",
          "arch": [
            "ia32"
          ]
        }
      ]
    },
    "linux": {
      "icon": "build/icons"
    }
  }

我测试的完整pachage.json

{
  "name": "ele",
  "version": "1.0.0",
  "description": "electron-demo",
  "main": "main.js",
  "dependencies": {
    "@electron/remote": "^2.0.8",
    "electron-reloader": "^1.2.3",
    "npm": "^8.5.4"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "electron": "electron .",
    "watch": "watchify app/appEntry.js -t babelify -o public/js/bundle.js --debug --verbose",
    "build": "electron-builder"
  },
  "build": {

   "appId": "com.fuck.app",
    
  "productName":"软件名",
  "win": {
    
    "icon": "./icon.ico",
    "target": [
    
    "nsis"
    
  ]
    
  },
    
  "nsis": {
    
  "oneClick": false,
    
  "perMachine": true,
    
  "allowToChangeInstallationDirectory": true
    
  }
    
   },
   "electronDownload":{

    "mirror":"https://npm.taobao.org/mirrors/electron/"

  },
  "devDependencies": {
    "babel": "^6.5.2",
    "babel-plugin-transform-es2015-spread": "^6.8.0",
    "babel-plugin-transform-object-rest-spread": "^6.8.0",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.5.0",
    "babelify": "^7.3.0",
    "browserify": "^13.0.1",
    "electron-builder": "^22.14.13",
    "electron-packager": "^7.7.0",
    "electron-reload": "^1.0.0",
    "watchify": "^3.7.0"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

图标问题

使用png或者jpg文件做图标

1、打包后图标未显示或者错误

打包后,会在打包目录中生成.icon-ico文件夹

文件夹内会生成我们要使用的图标文件icon.ico

生成后替换配置我们在目录中的jpg或者ico等文件。

重新打包即可。

2、测试图标正常但是打包后运行的图标显示错误

可能是图标路径配置不正确使用以下绝对路径方式配置!

main.js

我的Electron个人学习笔记_第8张图片

此时再打包即可


electron结合框架开发

创建vue项目

安装electron

加运行脚本: "electron": "electron .",

"main": "main.js",

我的Electron个人学习笔记_第9张图片

并写一个main.js

正常写

加载vue项目的url

mainWindow.loadURL('http://localhost:8080/#/')

即可完成!

上线时将vue打包的index.html引入!

直接使用模板创建electron-vue

项目地址:

github:https://github.com/simulatedgreg/electron-vue

npm install -g vue-cli
npm i -g @vue/cli-init

vue init simulatedgreg/electron-vue 项目名

你可能感兴趣的:(electron)