1. 使用electron-vue新建基於vue
的electron
環境,更多配置請訪問源專案
npm i -g vue-cli
vue init simulatedgreg/electron-vue my-project
cd my-project
npm i
npm run dev
複製程式碼
2. 打通electron
主程式與渲染程式的通訊
定義常量作為
channel
,也就是事件型別名稱
const CLIENT_NORMAL_MSG = 'CLIENT_NORMAL_MSG' // 渲染程式發出訊息型別
const CRAWLER_NORMAL_MSG = 'CRAWLER_NORMAL_MSG' // 主程式發出訊息型別
複製程式碼
渲染程式
在渲染程式中,使用vue plugin
的形式,具體參見vue
官方文件外掛
ipcRenderer
是eventEmitter的一個例項,在渲染程式中使用,你可以通過它來像主程式傳送同步和非同步訊息,也可以通過它來接收來自主程式的訊息
const { ipcRenderer } = require('electron')
const ipcService = Object.create(null)
const callbackCache = []
ipcService.install = Vue => {
Vue.prototype.$ipcRenderer = {
send: (msgType, msgData) => {
ipcRenderer.send(CLIENT_NORMAL_MSG, {
type: msgType,
data: msgData,
})
},
on: (type, callback) => {
callbackCache.push({
type,
callback,
})
}
}
ipcRenderer.on(CRAWLER_NORMAL_MSG, (sender, msg) => {
callbackCache.forEach(cache => {
if (cache.type === msg.type) {
cache.callback && cache.callback(msg.data)
}
})
}) // 監聽主程式的訊息
}
export default ipcService
複製程式碼
在vue
專案中通過this.$ipcRenderer.on
的方式新增主程式傳送訊息的監聽,通過this.$ipcRenderer.send
的方式向主程式傳送訊息,保證發出訊息均為CLIENT_NORMAL_MSG
型別,收到訊息均為CRAWLER_NORMAL_MSG
,通過訊息中的二級固定引數type
來區分具體型別,並可以通過detach
的方式來取消特定的型別的訊息的監聽
最後在Vue
的入口檔案,也就是渲染程式的入口檔案使用上面定義的外掛 Vue.use(ipcService)
渲染程式中的配置完成
主程式
使用class
的方式來定義,需要傳入兩個引數來例項化這個class
,需要傳入兩個引數,listener
為監聽訊息者,sender
為傳送訊息者
ipcMsgHandler
中包含了所有的handler
,為其傳入this
以便能夠在其中向渲染程式傳送訊息
import ipcMsgHandler from './ipcMsgHandler'
export default class Ipc {
constructor(listener, sender) {
this.listener = listener
this.sender = sender
this.addListener(CLIENT_NORMAL_MSG, this.handleFn.bind(this))
this.handlerList = ipcMsgHandler(this)
}
handleFn(event, data) {
try {
this.handlerList[data.type](event, data.data)
} catch (error) {
console.error('handler event error:' + error.message)
}
}
addListener(chanel, cb) {
this.listener.on(chanel, cb)
}
_sendMsg(chanel, msgBody) {
this.sender.send(chanel, msgBody)
}
sendToClient(type, data) {
this._sendMsg(CRAWLER_NORMAL_MSG, {
type,
data,
})
}
}
複製程式碼
初始狀態下ipcMsgHandler.js
檔案
export default _ipc => ({})
複製程式碼
在主程式的入口檔案(/src/main/index.js
)中對Ipc
這個class
例項化,其中需要使用的listener
為ipcMain
,ipcMain
和ipcRenderer
不同,它只負責對訊息的監聽,不復雜傳送訊息,這裡需要入口檔案中的mainWindow
下的webContents
作為訊息的傳送者,所以需要在mainWindow
建立成功之後再進行Ipc
的例項化
// ...
function createWindow() {
mainWindow = new BrowserWindow({
// ...
});
new IpcMgr(ipcMain, mainWindow.webContents)
}
複製程式碼
3. 完成具體功能開發
引入element-ui
,使用babel
配置css
按需載入,具體配置方式element-ui官網
分析掘金首頁資料來源
掘金首頁七種分類下資料均來自一個介面,https://timeline-merger-ms.juejin.im/v1/get_entry_by_rank?src=web&limit=20&category=xxx
,通過category
進行分類的區分
渲染程式開發
在App.js
中,在進入頁面和切換分類時向主程式傳送訊息
// ...
methods: {
startRequest() {
this.$ipcRenderer.send('start-request', this.activeCategory)
},
onRequestBack() {
this.$ipcRenderer.on('request-back', data => {
// todo...
})
},
}
複製程式碼
主程式開發
現在渲染程式中已經定義了兩種訊息型別start-request
和request-back
,start-request
告訴主程式開始執行任務,完成後request-back
告訴渲染程式任務完成,渲染程式收到訊息後通過收到的資料來對頁面進行操作。
在ipcMsgHandler.js
中進行擴充,使用axios
對介面內容進行抓取
import axios from 'axios'
const handlerList = _ipc => ({
['start-request'](event, category) {
const requestBack = data => {
_ipc.sendToClient('request-back', data)
}
axios.get(`https://timeline-merger-ms.juejin.im/v1/get_entry_by_rank?src=web&limit=20&category=${category}`)
.then(r => {
if(r.status === 200) {
requestBack({
success: true,
rows: r.data.d.entrylist
})
} else {
requestBack({
success: false,
error: `server error code: ${r.status}`
})
}
})
.catch(e => requestBack({
success: false,
error: `server error code: ${e.status} msg: ${e.message}`
}))
}
})
複製程式碼
請求完成後,通過requestBack
向渲染程式傳送訊息,渲染頁面,操作樣式調整,頁面看起來大概是這樣。
4. 增加連結跳轉到預設瀏覽器
在該專案中如果直接使用window.open
的方式來開啟的話,它會新彈出一個electron
視窗,所有連線跳轉也需要用到ipc
的方式
在electron
中,有一個shell
物件,它提供一個openExternal
的方法來在預設瀏覽器中開啟連結
在ipcMsgHandler.js
中新增以下內容
const { shell } = require('electron')
export default _ipc => ({
['open-shell'](event, url) {
shell.openExternal(url)
},
// ...
})
複製程式碼
現在就可以在vue
中通過this.$ipcRenderer.send('open-shell', url)
的方式來在預設瀏覽器中開啟連結了
一個通過打通IPC
通訊方式的掘金首頁概覽客戶端就完成了,通過npm run build
就可以對這個應用進行打包了
PS: 其實在electron
中是可以支援跨域訪問的,只需要在建立視窗的時候加上一下配置項就行了,不過結果其實並不重要,重要的是過程了
webPreferences: {
webSecurity: false,
}
複製程式碼
以上程式碼都可以在github上找到,歡迎star~~~