electron
入門基礎筆記,這裡記錄一下。- 文章發表於Poetry`s Blog
- 專案原始碼,供入門Electron學習參考
本文面向新人、沒有接觸過
Electron
的同學,做了一些基礎的知識梳理,助你快速入門。
一、前言
NW.js
和Electron
都可以用前端的知識來開發桌面應用。NW.js
和Electron
起初是同一 個作者開發。後來種種原因分為兩個產品。一個命名為NW.js
(英特爾公司提供技術支援)、 另一命名為Electron
(Github 公司提供技術支援)。NW.js
和Electron
可以用Nodejs
中幾乎所有的模組。NW.js
和Electron
不僅可以把html
寫的web
頁面打包成跨平臺可以安裝到電腦上面的軟體,也可以通過javascript
訪問操作 系統原生的UI
和Api
(控制視窗、新增選單專案、托盤應用選單、讀寫檔案、訪問剪貼簿)。
github
的atom
編輯器、微軟的vscode
編輯器,包括阿里內部的一些 軟體也是用electron
開發的
1. Electron 是由誰開發的?
Electron
是由Github
開發
2. Electron 是什麼?
Electron
是一個用HTML
,CSS
和JavaScript
來構建跨平臺桌面應用程式的一個開源庫
3. Electron 把 HTML,CSS 和 JavaScript 組合的程式構建為跨平臺桌面應用程式的原理 是什麼?
原理為
Electron
通過將Chromium
和Node.js
合併到同一個執行時環境中,並將其打包為Mac
,Windows
和Linux
系統下的應用來實現這一目的。
4. Electron 何時出現的,為什麼會出現?
Electron
於2013
年作為構建Atom
的框架而被開發出來。這兩個專案在2014
春季開源。 (Atom:為 Github 上可程式設計的文字編輯器)
一些歷史:
2013
年4
月Atom Shell
專案啟動 。2014
年5
月Atom Shell
被開源 。2015
年4
月Atom Shell
被重新命名為Electron
2016
年5
月Electron
釋出了v1.0.0
版本
5. Electron 當前流行程度?
目前
Electron
已成為開源開發者、初創企業和老牌公司常用的開發工具。
6. Electron 當前由那些人在維護支援?
Electron
當前由Github
上的一支團隊和一群活躍的貢獻者維護。有些貢獻者是獨立開發者,有些則在用Electron
構建應用的大型公司裡工作。
7. Electron 新版本多久釋出一次?
Electron
的版本釋出相當頻繁。每當Chromium
、Node.js
有重要的bug
修復,新API
或是版本更新時Electron
會發布新版本。
- 一般
Chromium
發行新的穩定版後的一到兩週之內,Electron
中Chromium
的版本會對其進行更新,具體時間根據升級所需的工作量而定。
一般Node.js
發行新的穩定版一個月後,Electron
中Node.js
的版本會對其進行更新,具 體時間根據升級所需的工作量而定。
8. Electron 的核心理念是什麼?
Electron
的核心理念是:保持Electron
的體積小和可持續性開發。
如:為了保持Electron
的小巧 (檔案體積) 和可持續性開發 (以防依賴庫和API
的泛濫) ,Electron
限制了所使用的核心專案的數量。
比如Electron
只用了Chromium
的渲染庫而不是其全部元件。這使得升級Chromium
更加容易,但也意味著Electron
缺少了Google Chrome
裡的一些瀏覽器相關的特性。 新增到Electron
的新功能應該主要是原生API
。 如果可以的話,一個功能應該儘可能的成 為一個Node.js
模組。
9. Electron 當前的最新版本為多少?
Electron
當前的最新版本為4.0.1
(當前時間為2019
年1
月6
號)
二、環境搭建
1. 安裝 electron
npm install -g electron
複製程式碼
2. 克隆一個倉庫、快速啟動一個專案
# 克隆示例專案的倉庫
git clone https://github.com/electron/electron-quick-start
# 進入這個倉庫
cd electron-quick-start
# 安裝依賴並執行
npm install && npm start
複製程式碼
3. 手動搭建一個 electron 專案
- 新建一個專案目錄 例如:
electrondemo01
- 在
electrondemo01
目錄下面新建三個檔案:index.html
、main.js
、package.json
index.html
裡面用css
進行佈局(以前怎麼寫現在還是怎麼寫)- 在
main.js
中寫如下程式碼
var electron =require(`electron`); //electron 物件的引用
const app=electron.app; //BrowserWindow 類的引用
const BrowserWindow=electron.BrowserWindow;
let mainWindow=null; //監聽應用準備完成的事件 app.on(`ready`,function(){
//監聽應用準備完成的事件
app.on(`ready`,function(){
//建立視窗
mainWindow=new BrowserWindow({width: 800, height: 600}); mainWindow.loadFile(`index.html`);
mainWindow.on(`closed`, function () {
mainWindow = null; })
})
})
//監聽所有視窗關閉的事件
app.on(`window-all-closed`, function () {
// On OS X it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== `darwin`) {
app.quit();
}
})
複製程式碼
- 執行
electron . #注意:命令後面有個點
複製程式碼
4. electron-forge 搭建一個 electron 專案
electron-forge
相當於electron
的一個腳手架,可以讓我們更方便的建立、執行、打包electron
專案
npm install -g electron-forge
electron-forge init my-new-app
cd my-new-app
npm start
複製程式碼
三、Electron 執行流程
3.1 Electron 執行的流程
3.2 Electron 主程式和渲染程式
Electron
執行package.json
的main
指令碼的程式被稱為主程式。- 在主程式中執行的指令碼通過建立
web
頁面來展示使用者介面。 一個Electron
應用總是有且只有一個主程式。 - 由於
Electron
使用了Chromium
(谷歌瀏覽器)來展示web
頁面,所以Chromium
的 多程式架構也被使用到。 每個Electron
中的web
頁面執行在它自己的渲染程式中。 - 主程式使用
BrowserWindow
例項建立頁面。每個BrowserWindow
例項都在自己的渲 染程式裡執行頁面。 當一個BrowserWindow
例項被銷燬後,相應的渲染程式也會被終止
- 程式:程式是計算機中的程式關於某資料集合上的一次執行活動,是 系統進行資源分配和排程的基本單位,是作業系統結構的基礎。
- 執行緒:在一個程式裡的一個執行路線就叫做執行緒(
thread
)。更準確的定義是: 執行緒是“一個程式內部的控制序列”。 - 執行緒和程式:一個程式至少有一個程式,一個程式至少有一個執行緒
3.3 Electron 渲染程式中通過 Nodejs 讀取本地檔案
在普通的瀏覽器中,
web
頁面通常在一個沙盒環境中執行,不被允許去接觸原生的資源。 然而Electron
的使用者在Node.js
的API
支援下可以在頁面中和作業系統進行一些底層交 互。
Nodejs
在主程式和渲染程式中都可以使用。渲染程式因為安全限制,不能直接操作生GUI
。雖然如此,因為整合了 Nodejs,渲染程式也有了作業系統底層API
的能力,Nodejs
中常用的Path
、fs
、Crypto
等模組在Electron
可以直接使用,方便我們處理連結、路徑、 檔案MD5
等,同時npm
還有成千上萬的模組供我們選擇。
var fs = require(`fs`);
var content = document.getElementById(`content`);
var button = document.getElementById(`button`);
button.addEventListener(`click`,function(e){
fs.readFile(`package.json`,`utf8`,function(err,data){
content.textContent = data;
console.log(data);
});
});
複製程式碼
3.4 Electron 開啟除錯模式
mainWindow.webContents.openDevTools();
複製程式碼
四、Electron 模組介紹
Electron
模組介紹、remote
模組、通 過BrowserWindow
開啟新視窗
4.1 Electron 主程式和渲染程式中的模組
4.2 Electron remote 模組
remote
模組提供了一種在渲染程式(網頁)和主程式之間進行程式間通訊(IPC
)的簡便途徑
Electron
中, 與GUI
相關的模組(如dialog
,menu
等)只存在於主程式,而不在渲染程式中 。為了能從渲染程式中使用它們,需要用ipc
模組來給主程式傳送程式間訊息。使用remote
模組,可以呼叫主程式物件的方法,而無需顯式地傳送程式間訊息,這類似於Java
的RMI
4.3 通過BrowserWindow 開啟新視窗
Electron
渲染程式中通過remote
模組呼叫主程式中的BrowserWindow
開啟新視窗
// 主程式程式碼
const electron = require(`electron`);
// 控制應用生命週期的模組
const {app} = electron;
// 建立本地瀏覽器視窗的模組
const {BrowserWindow} = electron;
// 指向視窗物件的一個全域性引用,如果沒有這個引用,那麼當該 javascript 物件被垃圾回收 的
// 時候該視窗將會自動關閉
let win;
function createWindow() {
// 建立一個新的瀏覽器視窗
win = new BrowserWindow({width: 1104, height: 620});//570+50
// 並且裝載應用的 index.html 頁面
win.loadURL(`file://${__dirname}/html/index.html`);
// 開啟開發工具頁面
win.webContents.openDevTools();
//當視窗關閉時呼叫的方法
win.on(`closed`, () => {
// 解除視窗物件的引用,通常而言如果應用支援多個視窗的話,你會在一個陣列裡 // 存放視窗物件,在視窗關閉的時候應當刪除相應的元素。
win = null;
});
}
// 當 Electron 完成初始化並且已經建立了瀏覽器視窗,則該方法將會被呼叫。
// 有些 API 只能在該事件發生後才能被使用
app.on(`ready`, createWindow);
// 當所有的視窗被關閉後退出應用
app.on(`window-all-closed`, () => {
// 對於 OS X 系統,應用和相應的選單欄會一直啟用直到使用者通過 Cmd + Q 顯式退出
if (process.platform !== `darwin`) {
app.quit();
}
});
app.on(`activate`, () => {
// 對於 OS X 系統,當 dock 圖示被點選後會重新建立一個 app 視窗,並且不會有其他
// 視窗開啟
if (win === null) {
createWindow();
}
});
// 在這個檔案後面你可以直接包含你應用特定的由主程式執行的程式碼。
// 也可以把這些程式碼放在另一個檔案中然後在這裡匯入
複製程式碼
// 渲染程式程式碼 /src/render/index.js
// 開啟新視窗屬性用法有點類似vscode開啟新的視窗
const btn = document.querySelector(`#btn`);
const path = require(`path`);
const BrowerWindow = require(`electron`).remote.BrowserWindow;
btn.onclick = () => {
win = new BrowerWindow({
width: 300,
height: 200,
frame: false, // false隱藏關閉按鈕、選單選項 true顯示
fullscreen:true, // 全屏展示
transparent: true
})
win.loadURL(path.join(`file:`,__dirname,`news.html`));
win.on(`close`,()=>{win = null});
}
複製程式碼
五、自定義頂部選單/右鍵選單
5.1 主程式中呼叫Menu模組-自定義軟體頂部選單
Electron
中Menu
模組可以用來建立原生選單,它可用作應用選單和context
選單
這個模組是一個主程式的模組,並且可以通過
remote
模組給渲染程式呼叫
// main/menu.js
const { Menu } = require(`electron`)
// 文件 https://electronjs.org/docs/api/menu-item
// 選單專案
let menus = [
{
label: `檔案`,
submenu: [
{
label: `新建檔案`,
accelerator: `ctrl+n`, // 繫結快捷鍵
click: function () { // 繫結事件
console.log(`新建檔案`)
}
},
{
label: `新建視窗`,
click: function () {
console.log(`新建視窗`)
}
}
]
},
{
label: `編輯`,
submenu: [
{
label: `複製`,
role: `copy` // 呼叫內建角色實現對應功能
},
{
label: `剪下`,
role: `cut` // 呼叫內建角色實現對應功能
}
]
},
{
label: `檢視`,
submenu: [
{
label: `瀏覽`
},
{
label: `搜尋`
}
]
}
]
let m = Menu.buildFromTemplate(menus)
Menu.setApplicationMenu(m)
複製程式碼
// 在主程式src/index.js中引入
const createWindow = () => {
// 建立選單
// 引入選單模組
require(`./main/menu.js`)
};
複製程式碼
我們給選單繫結事件,在命令列控制檯可以看到
5.2 渲染程式中呼叫Menu模組
不推薦使用這種方式,建議在主程式中使用
1. remote
通過
remote
呼叫主程式的方法
// 選單引入的方式發生變化
const { Menu } = require(`electron`).remote
// 其他程式碼和上面選單一樣
// ...
複製程式碼
2. 加入index.html
<script src="render/menu.js"></script>
複製程式碼
5.3 渲染程式中自定義右鍵選單
1. 定義選單
// render/menu.js
// 在渲染程式中通過remote模組呼叫主程式中的模組
const { Menu } = require(`electron`).remote
const { remote } = require(`electron`)
// 文件 https://electronjs.org/docs/api/menu-item
// 選單專案
let menus = [
{
label: `檔案`,
submenu: [
{
label: `新建檔案`,
accelerator: `ctrl+n`, // 繫結快捷鍵
click: function () { // 繫結事件
console.log(`新建檔案`)
}
},
{
label: `新建視窗`,
click: function () {
console.log(`新建視窗`)
}
}
]
},
{
label: `編輯`,
submenu: [
{
label: `複製`,
role: `copy` // 呼叫內建角色實現對應功能
},
{
label: `剪下`,
role: `cut` // 呼叫內建角色實現對應功能
}
]
},
{
label: `檢視`,
submenu: [
{
label: `瀏覽`
},
{
label: `搜尋`
}
]
}
]
let m = Menu.buildFromTemplate(menus)
// Menu.setApplicationMenu(m)
// 繫結右鍵選單
window.addEventListener(`contextmenu`, (e)=>{
e.preventDefault()
m.popup({
window: remote.getCurrentWindow()
})
}, false)
複製程式碼
2. 引入
<!--index.html-->
<script src="render/menu.js"></script>
複製程式碼
六、程式通訊
6.1 主程式與渲染程式之間的通訊
有時候我們想在渲染程式中通過一個事件去執行主程式裡面的方法。或者在渲染程式中通知 主程式處理事件,主程式處理完成後廣播一個事件讓渲染程式去處理一些事情。這個時候就 用到了主程式和渲染程式之間的相互通訊
Electron
主程式,和渲染程式的通訊主要用到兩個模組:ipcMain
和ipcRenderer
ipcMain
:當在主程式中使用時,它處理從渲染器程式(網頁)傳送出來的非同步和同步資訊,當然也有可能從主程式向渲染程式傳送訊息。ipcRenderer
: 使用它提供的一些方法從渲染程式 (web
頁面) 傳送同步或非同步的訊息到主程式。 也可以接收主程式回覆的訊息
6.1.1 渲染程式給主程式傳送非同步訊息
間接實現渲染程式執行主程式裡面的方法
1. 引入ipcRender
<!--src/index.html-->
<button id="send">在 渲染程式中執行主程式裡的方法(非同步)</button>
<script src="render/ipcRender.js"></script>
複製程式碼
2. 引入ipcMain
// 在主程式src/index.js中引入
const createWindow = () => {
// 建立選單
// 引入選單模組
require(`./main/ipcMain.js`)
};
複製程式碼
3. 渲染程式傳送訊息
// src/render/ipcRender.js
//渲染程式
let send = document.querySelector(`#send`);
const { ipcRenderer } = require(`electron`);
send.onclick = function () {
// 傳遞訊息給主程式
// 非同步
ipcRenderer.send(`sendMsg`, {name:`poetries`, age: 23})
}
複製程式碼
2. 主程式接收訊息
// src/main/ipcMain.js
//主程式
const { ipcMain } = require(`electron`)
// 主程式處理渲染程式廣播資料
ipcMain.on(`sendMsg`, (event, data)=> {
console.log(`data
`, data)
console.log(`event
`, event)
})
複製程式碼
6.1.2 渲染程式傳送訊息,主程式接收訊息並反饋
渲染程式給主程式傳送非同步訊息,主程式接收到非同步訊息以後通知渲染程式
1. 引入ipcRender
<!--src/index.html-->
<button id="sendFeedback">在 渲染程式中執行主程式裡的方法,並反饋給主程式(非同步)</button>
<script src="render/ipcRender.js"></script>
複製程式碼
2. 引入ipcMain
// 在主程式src/index.js中引入
const createWindow = () => {
// 建立選單
// 引入選單模組
require(`./main/ipcMain.js`)
};
複製程式碼
3. 渲染程式傳送訊息
// src/render/ipcRender.js
//渲染程式
let sendFeedback = document.querySelector(`#sendFeedback`);
const { ipcRenderer } = require(`electron`);
// 向主程式傳送訊息
sendFeedback.onclick = function () {
// 觸發主程式裡面的方法
ipcRenderer.send(`sendFeedback`, {name:`poetries`, age: 23})
}
複製程式碼
4. 主程式收到訊息處理並廣播反饋通知渲染程式
// src/main/ipcMain.js
//主程式
const { ipcMain } = require(`electron`)
// 主程式處理渲染程式廣播資料,並反饋給渲染程式
ipcMain.on(`sendFeedback`, (event, data)=> {
// console.log(`data
`, data)
// console.log(`event
`, event)
// 主程式給渲染程式廣播資料
event.sender.send(`sendFeedbackToRender`, `來自主程式的反饋`)
})
複製程式碼
5. 渲染程式處理主程式廣播的資料
// src/render/ipcRender.js
// 向主程式傳送訊息後,接收主程式廣播的事件
ipcRenderer.on(`sendFeedbackToRender`, (e, data)=>{
console.log(`event
`, e)
console.log(`data
`, data)
})
複製程式碼
6.1.3 渲染程式給主程式傳送同步訊息
1. 引入ipcRender
<!--src/index.html-->
<button id="sendSync">渲染程式和主程式同步通訊</button>
<script src="render/ipcRender.js"></script>
複製程式碼
2. 引入ipcMain
// 在主程式src/index.js中引入
const createWindow = () => {
// 建立選單
// 引入選單模組
require(`./main/ipcMain.js`)
};
複製程式碼
3. 渲染程式給主程式同步通訊
// src/render/ipcMain.js
let sendSync = document.querySelector(`#sendSync`);
// 渲染程式和主程式同步通訊
sendSync.onclick = function () {
// 同步廣播資料
let msg = ipcRenderer.sendSync(`sendsync`, {name:`poetries`, age: 23})
// 同步返回主程式反饋的資料
console.log(`msg
`, msg)
}
複製程式碼
4. 主程式接收資料處理
// src/main/ipcMain.js
// 渲染程式和主程式同步通訊 接收同步廣播
ipcMain.on(`sendsync`, (event, data)=> {
// console.log(`data
`, data)
// console.log(`event
`, event)
// 主程式給渲染程式廣播資料
event.returnValue =`渲染程式和主程式同步通訊 接收同步廣播,來自主程式的反饋.`;
})
複製程式碼
6.1.4 渲染程式廣播通知主程式開啟視窗
一般都是在渲染程式中執行廣播操作,去通知主程式完成任務
1. 引入openWindow
<!--src/index.html-->
<button id="sendSync">渲染程式和主程式同步通訊</button>
<script src="render/openWindow.js"></script>
複製程式碼
2. 引入ipcMain2
// 在主程式src/index.js中引入
const createWindow = () => {
// 建立選單
// 引入選單模組
require(`./main/ipcMain2.js`)
};
複製程式碼
3. 渲染程式通知主程式開啟視窗
// src/render/openWindow.js
/* eslint-disable */
let openWindow = document.querySelector(`#openWindow`);
var { ipcRenderer } = require(`electron`);
// 渲染程式和渲染程式直接的通訊========
openWindow.onclick = function () {
// 通過廣播的形式 通知主程式執行操作
ipcRenderer.send(`openwindow`, {name:`poetries`, age: 23})
}
複製程式碼
4. 主程式收到通知執行操作
// src/main/ipcMain2.js
/* eslint-disable */
let { ipcMain,BrowserWindow } = require(`electron`)
const path = require(`path`)
let win;
// 接收到廣播
ipcMain.on(`openwindow`, (e, data)=> {
// 呼叫window開啟新視窗
win = new BrowserWindow({
width: 400,
height: 300,
});
win.loadURL(path.join(`file:`,__dirname, `../news.html`));
win.webContents.openDevTools()
win.on(`closed`, () => {
win = null;
});
})
複製程式碼
6.2 渲染程式與渲染程式之間的通訊
也就是兩個視窗直接的通訊
6.2.1 localstorage傳值
Electron
渲染程式通過localstorage
給另一個渲染程式傳值
1. 引入openWindow
<!--src/index.html-->
<button id="sendSync">渲染程式和主程式同步通訊</button>
<script src="render/openWindow.js"></script>
複製程式碼
2. 引入ipcMain2
// 在主程式src/index.js中引入
const createWindow = () => {
// 建立選單
// 引入選單模組
require(`./main/ipcMain2.js`)
};
複製程式碼
3. 渲染程式通知主程式開啟視窗
// src/render/openWindow.js
/* eslint-disable */
let openWindow = document.querySelector(`#openWindow`);
var { ipcRenderer } = require(`electron`);
// 渲染程式和渲染程式直接的通訊========
openWindow.onclick = function () {
// 通過廣播的形式 通知主程式執行操作
ipcRenderer.send(`openwindow`, {name:`poetries`, age: 23})
// ======= localstorage傳值 =====
localStorage.setItem(`username`, `poetries`)
}
複製程式碼
4. 新建news頁面
<!--src/news.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
news page
</body>
<script src="render/news.js"></script>
</html>
複製程式碼
// src/render/news.js
let username = localStorage.getItem(`username`)
console.log(username)
複製程式碼
5. 主程式收到通知執行操作
// src/main/ipcMain2.js
/* eslint-disable */
let { ipcMain,BrowserWindow } = require(`electron`)
const path = require(`path`)
let win;
// 接收到廣播
ipcMain.on(`openwindow`, (e, data)=> {
// 呼叫window開啟新視窗
win = new BrowserWindow({
width: 400,
height: 300,
});
win.loadURL(path.join(`file:`,__dirname, `../news.html`));
win.webContents.openDevTools()
win.on(`closed`, () => {
win = null;
});
})
複製程式碼
6.2.2 BrowserWindow和webContents方式實現
通過
BrowserWindow
和webContents
模組實現渲染程式和渲染程式的通訊
webContents
是一個事件發出者.它負責渲染並控制網頁,也是BrowserWindow
物件的屬性
需要了解的幾個知識點
- 獲取當前視窗的
id
const winId = BrowserWindow.getFocusedWindow().id;
複製程式碼
- 監聽當前視窗載入完成的事件
win.webContents.on(`did-finish-load`,(event) => {
})
複製程式碼
- 同一視窗之間廣播資料
win.webContents.on(`did-finish-load`,(event) => {
win.webContents.send(`msg`,winId,`我是 index.html 的資料`);
})
複製程式碼
- 通過
id
查詢視窗
let win = BrowserWindow.fromId(winId);
複製程式碼
下面是具體演示
1. 引入openWindow
<!--src/index.html-->
<button id="sendSync">渲染程式和主程式同步通訊</button>
<script src="render/openWindow.js"></script>
複製程式碼
2. 引入ipcMain2
// 在主程式src/index.js中引入
const createWindow = () => {
// 建立選單
// 引入選單模組
require(`./main/ipcMain2.js`)
};
複製程式碼
3. 渲染程式通知主程式開啟視窗
// src/render/openWindow.js
/* eslint-disable */
let openWindow = document.querySelector(`#openWindow`);
var { ipcRenderer } = require(`electron`);
// 渲染程式和渲染程式直接的通訊========
openWindow.onclick = function () {
// 通過廣播的形式 通知主程式執行操作
ipcRenderer.send(`openwindow`, {name:`poetries`, age: 23})
}
複製程式碼
4. 主程式收到通知執行操作
// src/main/ipcMain2.js
let { ipcMain,BrowserWindow } = require(`electron`)
const path = require(`path`)
let win;
// 接收到廣播
ipcMain.on(`openwindow`, (e, userInfo)=> {
// 呼叫window開啟新視窗
win = new BrowserWindow({
width: 400,
height: 300,
});
win.loadURL(path.join(`file:`,__dirname, `../news.html`));
// 新開視窗除錯模式
win.webContents.openDevTools()
// 把渲染程式傳遞過來的資料再次傳遞給渲染程式news
// 等待視窗載入完
win.webContents.on(`did-finish-load`, ()=>[
win.webContents.send(`toNews`, userInfo)
])
win.on(`closed`, () => {
win = null;
});
})
複製程式碼
5. news接收主程式傳遞的資料
資料經過渲染程式->主程式->
news
渲染程式
<!--news頁面-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
news page
</body>
<script src="render/news.js"></script>
</html>
複製程式碼
// src/render/news.js
var { ipcRenderer } = require(`electron`);
// let username = localStorage.getItem(`username`)
// console.log(username)
// 監聽主程式傳遞過來的資料
ipcRenderer.on(`toNews`,(e, userInfo)=>{
console.log(userInfo)
})
複製程式碼
那麼,這裡有一個問題,
news
程式接收到了廣播後如何給出反饋呢?
1. 在主程式中獲取視窗ID傳遞
// src/main/ipcMain2.js
let { ipcMain,BrowserWindow } = require(`electron`)
const path = require(`path`)
let win;
// 接收到廣播
ipcMain.on(`openwindow`, (e, userInfo)=> {
// 獲取當前視窗ID 放在第一行保險 因為後面也開啟了新視窗使得獲取的ID有問題
let winId = BrowserWindow.getFocusedWindow().id
// 呼叫window開啟新視窗
win = new BrowserWindow({
width: 400,
height: 300,
});
win.loadURL(path.join(`file:`,__dirname, `../news.html`));
// 新開視窗除錯模式
win.webContents.openDevTools()
// 把渲染程式傳遞過來的資料再次傳遞給渲染程式news
// 等待視窗載入完
win.webContents.on(`did-finish-load`, ()=>[
win.webContents.send(`toNews`, userInfo, winId)
])
win.on(`closed`, () => {
win = null;
});
})
複製程式碼
2. 在news程式中廣播資料
// src/render/news.js
var { ipcRenderer } = require(`electron`);
// 注意這裡 在渲染程式中需要從remote中獲取BrowserWindow
const BrowerWindow = require(`electron`).remote.BrowserWindow;
// let username = localStorage.getItem(`username`)
// console.log(username)
// 監聽主程式傳遞過來的資料
ipcRenderer.on(`toNews`,(e, userInfo, winId)=>{
// windID 第一個視窗ID
// 獲取對應ID的視窗
let firstWin = BrowerWindow.fromId(winId)
firstWin.webContents.send(`toIndex`, `來自news程式反饋的資訊`)
console.log(userInfo)
})
複製程式碼
3. 在另一個渲染程式中處理廣播
/* eslint-disable */
let openWindow = document.querySelector(`#openWindow`);
var { ipcRenderer } = require(`electron`);
// 渲染程式和渲染程式直接的通訊========
openWindow.onclick = function () {
// 傳遞訊息給主程式
ipcRenderer.send(`openwindow`, {name:`poetries`, age: 23})
// 傳遞給開啟的視窗 渲染程式和渲染程式直接的通訊
localStorage.setItem(`username`, `poetries`)
}
// 接收news渲染程式傳遞回來的訊息
ipcRenderer.on(`toIndex`, (e, data)=>{
console.log(`===`, data)
})
複製程式碼
七、Electron Shell 模組
7.1 Shell 模組使用
Electron Shell
模組在使用者預設瀏覽器 中開啟URL
以及Electron DOM webview
標籤。Shell
既屬於主程式模組又是渲染程式模組
shell
模組提供了整合其他桌面客戶端的關聯功能
1. 引入
<!--index.html-->
<button id="shellDom">通過shell開啟外部連結</button>
<script src="render/shell.js"></script>
複製程式碼
2. shell.js
// src/render/shell.js
const { shell } = require(`electron`)
let shellDom = document.querySelector(`#shellDom`);
shellDom.onclick = function (e) {
shell.openExternal(`https://github.com/poetries`)
}
複製程式碼
7.2 Electron DOM
<webview>
標籤
Webview
與iframe
有點相似,但是與iframe
不同,webview
和你的應用執行的是不同的程式。它不擁有渲染程式的許可權,並且應用和嵌入內容之間的互動全部都是非同步的。因為這能 保證應用的安全性不受嵌入內容的影響。
<!--src/index.html中引入-->
<webview id="webview" src="http://blog.poetries.top" style="position:fixed; width:100%; height:100%">
</webview>
複製程式碼
7.3 shell
模組<webview>
結合Menu
模組使用案例
1. 新建src/render/webview.js
/* eslint-disable */
var { ipcRenderer } = require(`electron`);
let myWebview = document.querySelector(`#myWebview`)
ipcRenderer.on(`openwebview`, (e, url)=>{
myWebview.src = url
})
複製程式碼
2. 引入src/index.html
<webview id="myWebview" src="http://blog.poetries.top" style="position:fixed; width:100%; height:100%">
</webview>
<script src="render/webview.js"></script>
複製程式碼
3. 新建src/main/menu.js
/* eslint-disable */
const { shell, Menu, BrowserWindow } = require(`electron`);
// 當前視窗渲染網頁
function openWebView(url) {
// 獲取當前視窗Id
let win = BrowserWindow.getFocusedWindow()
// 廣播通知渲染程式開啟webview
win.webContents.send(`openwebview`, url)
}
// 在視窗外開啟網頁
function openWeb(url) {
shell.openExternal(url)
}
let template = [
{
label: `幫助`,
submenu: [
{
label: `關於我們`,
click: function () {
openWeb(`http://blog.poetries.top`)
}
},
{
type: `separator`
},
{
label: `聯絡我們`,
click: function () {
openWeb(`https://github.com/poetries`)
}
}
]
},
{
label: `載入網頁`,
submenu: [
{
label: `部落格`,
click: function () {
openWebView(`http://blog.poetries.top`)
}
},
{
type: `separator` // 分隔符
},
{
label: `GitHub`,
click: function () {
openWebView(`https://github.com/poetries`)
}
},
{
type: `separator` // 分隔符
},
{
label: `簡書`,
click: function () {
openWebView(`https://www.jianshu.com/users/94077fcddfc0/timeline`)
}
}
]
},
{
label: `視訊網站`,
submenu: [
{
label: `優酷`,
click: function () {
openWebView(`https://www.youku.com`)
}
},
{
type: `separator` // 分隔符
},
{
label: `愛奇藝`,
click: function () {
openWebView(`https://www.iqiyi.com/`)
}
},
{
type: `separator` // 分隔符
},
{
label: `騰訊視訊`,
click: function () {
openWebView(`https://v.qq.com/`)
}
}
]
}
]
let m = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(m)
複製程式碼
4. 引入menu
// 在主程式src/index.js中引入
const createWindow = () => {
// 建立選單
// 引入選單模組
require(`./main/menu.js`)
};
複製程式碼
八、Electron dialog 彈出框
dialog
屬於主程式中的模組
dialog
模組提供了api
來展示原生的系統對話方塊,例如開啟檔案框,alert
框, 所以web
應用可以給使用者帶來跟系統應用相同的體驗
1. 在src/index.html中引入
<button id="showError">showError</button><br />
<button id="showMsg">showMsg</button><br />
<button id="showOpenDialog">showOpenDialog</button><br />
<button id="saveDialog">saveDialog</button><br />
<script src="render/dialog.js"></script>
複製程式碼
2. 新建render/dialog.js
// render/dialog.js
let showError = document.querySelector(`#showError`);
let showMsg = document.querySelector(`#showMsg`);
let showOpenDialog = document.querySelector(`#showOpenDialog`);
let saveDialog = document.querySelector(`#saveDialog`);
var {remote} = require(`electron`)
showError.onclick = function () {
remote.dialog.showErrorBox(`警告`, `操作有誤`)
}
showMsg.onclick = function () {
remote.dialog.showMessageBox({
type: `info`,
title: `提示資訊`,
message: `內容`,
buttons: [`確定`, `取消`]
},function(index){
console.log(index)
})
}
showOpenDialog.onclick = function () {
remote.dialog.showOpenDialog({
// 開啟資料夾
properties: [`openDirectory`, `openFile`]
// 開啟檔案
// properties: [`openFile`]
}, function (data) {
console.log(data)
})
}
saveDialog.onclick = function () {
remote.dialog.showSaveDialog({
title: `Save File`,
defaultPath: `/Users/poetry/Downloads/`,
// filters 指定一個檔案型別陣列,用於規定使用者可見或可選的特定型別範圍
filters: [
{ name: `Images`, extensions: [`jpg`, `png`, `gif`] },
{ name: `Movies`, extensions: [`mkv`, `avi`, `mp4`] },
{ name: `Custom File Type`, extensions: [`as`] },
{ name: `All Files`, extensions: [`*`] }
]
}, function (path) {
// 不是真的儲存 ,具體還需nodejs處理
console.log(path)
})
}
複製程式碼
showError
remote.dialog.showErrorBox(`警告`, `操作有誤`)
複製程式碼
showMessageBox
remote.dialog.showMessageBox({
type: `info`,
title: `提示資訊`,
message: `內容`,
buttons: [`確定`, `取消`]
},function(index){
console.log(index)
})
複製程式碼
showOpenDialog
remote.dialog.showOpenDialog({
// 開啟資料夾
properties: [`openDirectory`, `openFile`]
// 開啟檔案
// properties: [`openFile`]
}, function (data) {
console.log(data)
})
複製程式碼
showSaveDialog
remote.dialog.showSaveDialog({
title: `Save File`,
defaultPath: `/Users/poetry/Downloads/`,
// filters 指定一個檔案型別陣列,用於規定使用者可見或可選的特定型別範圍
filters: [
{ name: `Images`, extensions: [`jpg`, `png`, `gif`] },
{ name: `Movies`, extensions: [`mkv`, `avi`, `mp4`] },
{ name: `Custom File Type`, extensions: [`as`] },
{ name: `All Files`, extensions: [`*`] }
]
}, function (path) {
// 不是真的儲存 ,具體還需nodejs處理
console.log(path)
})
複製程式碼
九、實現一個類似EditPlus的簡易記事本程式碼編輯器
十、系統托盤、托盤右鍵選單、托盤圖示閃爍
系統托盤,托盤右鍵選單、托盤圖示閃爍 點選右上角關閉按鈕隱藏到托盤(仿防毒軟體)
1. 引入檔案
// src/index.js
const createWindow = () => {
require(`./main/tray.js`)
};
複製程式碼
2. Electron 建立工作列圖示以及工作列圖示右鍵選單
// src/main/tray.js
var {
Menu, Tray, app, BrowserWindow
} = require(`electron`);
const path = require(`path`);
var appIcon = new Tray(path.join(__dirname, `../static/lover.png`));
const menu = Menu.buildFromTemplate([
{
label: `設定`,
click: function() {} //開啟相應頁面
},
{
label: `幫助`,
click: function() {}
},
{
label: `關於`,
click: function() {}
},
{
label: `退出`,
click: function() {
// BrowserWindow.getFocusedWindow().webContents().send(`close-main-window`);
app.quit();
}
}])
// 滑鼠放上去提示資訊
appIcon.setToolTip(`hello poetries`);
appIcon.setContextMenu(menu);
複製程式碼
3. 監聽工作列圖示的單擊、雙擊事件
// 實現點選關閉按鈕,讓應用儲存在托盤裡面,雙擊托盤開啟
let win = BrowserWindow.getFocusedWindow()
win.on(`close`, (e)=>{
e.preventDefault()
win.hide()
})
iconTray.on(`double-click`, (e)=>{
win.show()
})
複製程式碼
4. Electron 點選右上角關閉按鈕隱藏工作列圖示
const win = BrowserWindow.getFocusedWindow();
win.on(`close`, (e) =>{
console.log(win.isFocused());
if (!win.isFocused()) {
win = null;
} else {
e.preventDefault();/*阻止應用退出*/
win.hide();/*隱藏當前視窗*/
}
})
複製程式碼
5. Electron 實現工作列閃爍圖示
var appIcon = new Tray(path.join(__dirname, `../static/lover.png`));
timer = setInterval(function() {
count++;
if (count % 2 == 0) {
appIcon.setImage(path.join(__dirname, `../static/empty.ico`))
} else {
appIcon.setImage(path.join(__dirname, `../static/lover.png`))
}
},
500);
複製程式碼
十一、訊息通知、監聽網路變 化、網路變化彈出通知框
11.1 訊息通知
1. Electron 實現訊息通知
Electron
裡面的訊息通知是基於h5
的通知api
實現的
1. 新建notification.js
// h5api實現通知
const path = require(`path`)
let options = {
title: `electron 通知API`,
body: `hello poetries`,
icon: path.join(`../static/img/favicon2.ico`) // 通知圖示
}
document.querySelector(`#showNotification`).onclick = function () {
let myNotification = new window.Notification(options.title, options)
// 訊息可點選
myNotification.onclick = function () {
console.log(`click notification`)
}
}
複製程式碼
2. 引入
<!--src/index.html-->
<button id="showNotification">彈出訊息通知</button>
<script src="render/notification.js"></script>
複製程式碼
mac
上的訊息通知
11.2 監聽網路變化
1. 基本使用
// 監聽網路變化
// 端開網路 再次連線測試
window.addEventListener(`online`, function(){
console.log(`online`)
});
window.addEventListener(`offline`, function(){
console.log(`offline`)
});
複製程式碼
2. 監聽網路變化實現訊息通知
// 端開網路 再次連線測試
// 監聽網路變化實現訊息通知
window.addEventListener(`online`, function(){
console.log(`online`)
});
window.addEventListener(`offline`, function(){
// 斷開網路觸發事件
var options = {
title: `QQ郵箱`,
body: `網路異常,請檢查你的網路`,
icon: path.join(`../static/img/favicon2.ico`) // 通知圖示
}
var myNotification = new window.Notification(options.title, options)
myNotification.onclick = function () {
console.log(`click notification`)
}
});
複製程式碼
十二、註冊全域性快捷鍵/剪下板事件/nativeImage 模組
Electron
註冊全域性快捷鍵 (globalShortcut
) 以及clipboard
剪 切板事件以及nativeImage
模組(實現類似播放器點選機器碼自動複製功 能)
12.1 註冊全域性快捷鍵
1. 新建src/main/shortCut.js
const {globalShortcut, app} = require(`electron`)
app.on(`ready`, ()=>{
// 註冊全域性快捷鍵
globalShortcut.register(`command+e`, ()=>{
console.log(1)
})
// 檢測快捷鍵是否註冊成功 true是註冊成功
let isRegister = globalShortcut.isRegistered(`command+e`)
console.log(isRegister)
})
// 退出的時候取消全域性快捷鍵
app.on(`will-quit`, ()=>{
globalShortcut.unregister(`command+e`)
})
複製程式碼
2. 引入src/index.js
// 注意在外部引入即可 不用放到app中
require(`./main/shortCut.js`)
複製程式碼
12.2 剪下板clipboard、nativeImage 模組
1. html
<!--src/index.html-->
<div>
<h2>雙擊下面資訊複製</h2>
<p id=`msg`>123456789</p>
<button id="plat">貼上</button><br />
<input id="text" type="text"/>
</div>.
<div>
<h2>複製圖片到介面</h2>
<button id="copyImg">複製圖片</button><br />
</div>
<script src="render/clipboard.js"></script>
複製程式碼
2. 新建src/render/clipboard.js
// clipboard可以在主程式或渲染程式使用
const { clipboard, nativeImage } = require(`electron`)
//複製
// 執行ctrl+v可看到複製的內容
// clipboard.writeText(`poetries`)
// clipboard.readText() //獲取複製的內容 貼上
// 雙擊複製訊息
let msg = document.querySelector(`#msg`)
let plat = document.querySelector(`#plat`)
let text = document.querySelector(`#text`)
msg.ondblclick = function () {
clipboard.writeText(msg.innerHTML)
alert(msg.innerHTML)
}
plat.onclick = function () {
text.value = clipboard.readText()
}
// 複製圖片顯示到介面
let copyImg = document.querySelector(`#copyImg`)
copyImg.onclick = function () {
// 結合nativeImage模組
let image = nativeImage.createFromPath(`../static/img/lover.png`)
// 複製圖片
clipboard.writeImage(image)
// 貼上圖片
let imgSrc = clipboard.readImage().toDataURL() // base64圖片
// 顯示到頁面上
let imgDom = new Image()
imgDom.src = imgSrc
document.body.appendChild(imgDom)
}
複製程式碼
十三、結合electron-vue
13.1 electron-vue 的使用
1. electron-vue 的一些資源
Electron-vue
文件 simulatedgreg.gitbooks.io/electron-vu…
2. electron-vue 環境搭建、建立專案
npm install -g vue-cli
vue init simulatedgreg/electron-vue my-project
cd my-project
yarn # or npm install
yarn run dev # or npm run dev
複製程式碼
3. electron-vue 目錄結構分析
13.2 electron-vue 中使用 sass/ElementUi
1. electron-vue UI 框架 ElementUi 的使用
2. electron-vue 中使用 sass
# 安裝 sass-loader:
npm install --save-dev sass-loader node-sass
複製程式碼
<!--vue 檔案中修改 style 為如下程式碼:-->
<style lang="scss">
body {
/* SCSS */
}
</style>
複製程式碼
13.3 electron-vue 中隱藏頂部選單隱藏
electron-vue 中隱藏頂部選單隱藏頂部最大化、最小化、關閉按鈕 自定最大化、最小化 、關閉按鈕
1. electron-vue 中隱藏頂部選單
// src/main/index.js
mainWindow.setMenu(null)
複製程式碼
2. electron-vue 中隱藏關閉 最大化 最小化按鈕
// src/main/index.js
mainWindow = new BrowserWindow({
height: 620,
useContentSize: true,
width: 1280,
frame: false /*去掉頂部導航 去掉關閉按鈕 最大化最小化按鈕*/
})
複製程式碼
3 .electron-vue 自定義關閉/最大化最小化按鈕
// 注意在mac下不需要監聽視窗最大最小化、以為系統預設支援,這個只是針對windows平臺
ipc.on(`window-min`,function() {
mainWindow.minimize();
})
//登入視窗最大化
ipc.on(`window-max`,function(){
if (mainWindow.isMaximized()) {
mainWindow.restore();
} else {
mainWindow.maximize();
}
})
ipc.on(`window-close`,function() {
mainWindow.close();
})
複製程式碼
4. electron-vue 自定義導航可拖拽
- 可拖拽的
css
:-webkit-app-region: drag;
- 不可拖拽的
css
:-webkit-app-region: no-drag;
13.4 使用electron-vue開發輿情監控系統
專案原始碼,僅做入門學習參考 github.com/poetries/yu…
13.4.1 配置開發環境
1. 專案搭建
npm install -g vue-cli
vue init simulatedgreg/electron-vue my-project
cd my-project
yarn # or npm install
yarn run dev # or npm run dev
複製程式碼
2. 安裝一些依賴
# 安裝 sass-loader:
npm install --save-dev sass-loader node-sass
# 安裝elementUI、js-md5
npm i element-ui js-md5 -S
複製程式碼
- 在
.electron-vue/webpack.renderer.config.js
中配置sass-loader
就可以編寫“sass`了
<!--vue 檔案中修改 style 為如下程式碼:-->
<style lang="scss">
body {
/* SCSS */
}
</style>
複製程式碼
13.4.2 主程式配置
1. src/main/index.js
function createWindow () {
// 去掉頂部選單
mainWindow.setMenu(null)
// 選單項
require(`./model/menu.js`);
// 系統托盤相關
require(`./model/tray.js`);
複製程式碼
2. src/main/menu.js
選單配置
const { Menu,ipcMain,BrowserWindow} = require(`electron`);
//右鍵選單
const contextMenuTemplate=[
{
label: `複製`, role: `copy` },
{
label: `黏貼`, role: `paste` },
{ type: `separator` }, //分隔線
{
label: `其他功能`,
click: () => {
console.log(`click`)
}
}
];
const contextMenu=Menu.buildFromTemplate(contextMenuTemplate);
ipcMain.on(`contextmenu`,function(){
contextMenu.popup(BrowserWindow.getFocusedWindow());
})
複製程式碼
3. src/main/tray.js
系統托盤配置
托盤點選監聽事件只有在
windows
下才生效,mac
系統預設支援
(function () {
const path=require(`path`);
const {app,Menu,BrowserWindow,Tray, shell} = require(`electron`);
//建立系統托盤
const tray = new Tray(path.resolve(__static, `favicon.png`))
//給托盤增加右鍵選單
const template= [
{
label: `設定`,
click: function () {
shell.openExternal(`http://blog.poetries.top`)
}
},
{
label: `幫助`,
click: function () {
shell.openExternal(`http://blog.poetries.top/2019/01/06/electron-summary`)
}
},
{
label: `關於`,
click: function () {
shell.openExternal(`https://github.com/poetries/yuqing-monitor-electron`)
}
},
{
label: `退出`,
click: function () {
// BrowserWindow.getFocusedWindow().webContents().send(`close-main-window`);
app.quit();
}
}
];
const menu = Menu.buildFromTemplate(template);
tray.setContextMenu(menu);
tray.setToolTip(`輿情監控系統`);
//監聽關閉事件隱藏到系統托盤
// 這裡需要注意:在window中才生效,mac下系統預設支援
// var win = BrowserWindow.getFocusedWindow();
// win.on(`close`,(e)=>{
// if(!win.isFocused()){
// win=null;
// }else{
// e.preventDefault(); /*阻止應用退出*/
// win.hide(); /*隱藏當前視窗*/
// }
// })
// //監聽托盤的雙擊事件
// tray.on(`double-click`,()=>{
// win.show();
// })
})()
複製程式碼
4. src/main/shortCut.js
快捷鍵配置
在src/main/index.js
中引入(require(`src/main/shortCut.js`)
)即可,不需要放到app
監控中
var {globalShortcut, app} = require(`electron`)
app.on(`ready`, ()=>{
// 註冊全域性快捷鍵
globalShortcut.register(`command+e`, ()=>{
console.log(1)
})
// 檢測快捷鍵是否註冊成功 true是註冊成功
let isRegister = globalShortcut.isRegistered(`command+e`)
console.log(isRegister)
})
// 退出的時候取消全域性快捷鍵
app.on(`will-quit`, ()=>{
globalShortcut.unregister(`command+e`)
})
複製程式碼
13.4.3 渲染程式配置
1. src/render/main.js配置
import Vue from `vue`
import axios from `axios`
import App from `./App`
import router from `./router`
import store from `./store`
import ElementUI from `element-ui`;
import `element-ui/lib/theme-chalk/index.css`;
import VueHighcharts from `vue-highcharts`;
import VueSocketIO from `vue-socket.io`
Vue.use(ElementUI);
Vue.use(VueHighcharts);
//引入socket.io配置連線
Vue.use(new VueSocketIO({
debug: true,
connection: `http://118.123.14.36:3000`,
vuex: {
store,
actionPrefix: `SOCKET_`,
mutationPrefix: `SOCKET_`
}
}))
if (!process.env.IS_WEB) Vue.use(require(`vue-electron`))
Vue.http = Vue.prototype.$http = axios
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
components: { App },
router,
store,
template: `<App/>`
}).$mount(`#app`)
複製程式碼
2. 路由配置src/renderer/router/index.js
import Vue from `vue`
import Router from `vue-router`
Vue.use(Router)
export default new Router({
routes: [
{
path: `/home`,
name: `home`,
component: require(`@/components/Home`).default
},
{
path: `/report`,
name: `report`,
component: require(`@/components/Report`).default
},
{
path: `/negativereport`,
name: `negativereport`,
component: require(`@/components/NegativeReport`).default
},
{
path: `/positivereport`,
name: `positivereport`,
component: require(`@/components/PositiveReport`).default
},
{
path: `/keyword`,
name: `keyword`,
component: require(`@/components/KeyWord`).default
},
{
path: `/alarm`,
name: `alarm`,
component: require(`@/components/Alarm`).default
},
{
path: `/msg`,
name: `msg`,
component: require(`@/components/Msg`).default
},
{
path: `*`,
redirect: `/home`
}
]
})
複製程式碼
3. 在渲染程式中使用主程式方式
// electron掛載到了vue例項上 $electron
this.$electron.shell
複製程式碼
13.4.4 多平臺打包
需要注意的是打包
mac
版本在mac
系統上打包,打包window
則在windows
上打包,可以避免很多問題
# 在不同平臺上執行即可打包應用
npm run build
複製程式碼
13.4.4.1 打包介紹
1. electron 中構建應用最常用的模組
electron-packager
electron-builder
electron-packager
和electron-builder
在自己單獨建立的應用用也可以完成打包功 能。但是由於配置太複雜所以我們不建議單獨配置
2. electron-forge
electron-forge package
electron-forge make
複製程式碼
3. electron-vue中的打包方式
# https://simulatedgreg.gitbooks.io/electron-vue/content/cn/using-electron-packager. html
# 之需要執行一條命令
npm run build
複製程式碼
13.4.4.2 修改應用資訊
1. 修改package.json
2. 修改src/index.ejs標題資訊
3. 修改build/icons圖示
13.4.4.3 打包遇到的問題
1. 建立應用托盤的時候可能會遇到錯誤
- 把托盤圖片放在根目錄
static
裡面,然後注意下面寫法。
var tray = new Tray(path.join(__static,`favicon.ico`))
複製程式碼
- 如果托盤路徑沒有問題,還是包托盤相關錯誤的話,把托盤對應的圖片換成
.png
格式重試
2. 模組問題可能會遇到的錯誤
解決辦法
- 刪掉
node_modules
然後重新用npm install
安裝依賴 - 用
yarn
來安裝模組 - 用手機建立一個熱點電腦連上熱點重試
最後執行
yarn run build
即可
專案截圖
輿情監控系統頁面
系統系統托盤、
electron
訊息通知 (類似騰訊新聞)
專案原始碼 github.com/poetries/yu…