Merge pull request #9 from i-CNNN/master

Demo:渲染进程与主进程使用原生IPC通信
This commit is contained in:
Wallace Gao
2021-03-23 16:29:12 +08:00
committed by GitHub
12 changed files with 227 additions and 27 deletions

View File

@@ -1,21 +1,60 @@
'use strict';
const AutoLaunchManager = require('../lib/AutoLaunch');
'use strict'
const { app, dialog } = require('electron')
const AutoLaunchManager = require('../lib/AutoLaunch')
exports.autoLaunchEnable = function () {
const autoLaunchManager = new AutoLaunchManager();
const enable = autoLaunchManager.enable();
return enable;
const autoLaunchManager = new AutoLaunchManager()
const enable = autoLaunchManager.enable()
return enable
}
exports.autoLaunchDisable = function () {
const autoLaunchManager = new AutoLaunchManager();
const disable = autoLaunchManager.disable();
return disable;
const autoLaunchManager = new AutoLaunchManager()
const disable = autoLaunchManager.disable()
return disable
}
exports.autoLaunchIsEnabled = function () {
const autoLaunchManager = new AutoLaunchManager();
const isEnable = autoLaunchManager.isEnabled();
return isEnable;
}
const autoLaunchManager = new AutoLaunchManager()
const isEnable = autoLaunchManager.isEnabled()
return isEnable
}
exports.appExit = function () {
app.exit()
}
exports.appRelaunch = function () {
app.relaunch()
app.exit()
}
/**
* 选择本地文件夹
* @param title 弹出框的标题
* @return {Promise<*>}
*/
exports.choiceFolder = async function (title = '') {
return await dialog.showOpenDialog({
properties: ['openDirectory'],
title: title
})
}
/**
* 选择本地文件
* @param title 弹出框的标题
* @param extensions 后缀名集合 e.g: ['exe','txt','png']
* @return {Promise<*>}
*/
exports.choiceFile = async function (title = '', extensions = []) {
return await dialog.showOpenDialog({
properties: ['openFile'],
filters: [{
extensions: extensions
}],
title: title
})
}

View File

@@ -37,6 +37,7 @@ const config = {
minHeight: 600,
webPreferences: {
//webSecurity: false,
contextIsolation: false, // 设置此项为false后才可在渲染进程中使用electron api
nodeIntegration: true,
preload: path.join(__dirname, '../preload.js')
},
@@ -78,7 +79,7 @@ exports.get = function (flag = '', env = 'prod') {
if (flag === 'webEgg') {
return config.egg;
}
if (flag === 'egg') {
const eggConfig = storage.getEggConfig();
if (env === 'prod' && eggConfig.port) {
@@ -90,8 +91,8 @@ exports.get = function (flag = '', env = 'prod') {
if (flag === 'autoUpdate') {
return config.autoUpdate;
}
return {};
};
exports = module.exports;
exports = module.exports;

6
electron/ipc/example.js Normal file
View File

@@ -0,0 +1,6 @@
const { answerRenderer } = require('./index')
answerRenderer('example.test', async (name) => {
const luckNum = (Math.random()*1000).toFixed()
return `${name}, 你的幸运数字是:${luckNum}`
})

40
electron/ipc/index.js Normal file
View File

@@ -0,0 +1,40 @@
const { ipcMain: ipc } = require('electron')
const path = require('path')
const fs = require('fs-extra')
/**
* 发送响应信息给渲染进程
* @param event
* @param channel
* @param data
* @private
*/
const _echo = (event, channel, data) => {
event.reply(`${channel}`, data)
}
/**
* 执行主进程函数,并响应渲染进程
* @param channel
* @param callback
*/
module.exports.answerRenderer = (channel, callback) => {
ipc.on(channel, async (event, param) => {
const result = await callback(param)
_echo(event, channel, result)
})
}
/**
* 加载所有的主程序
*/
module.exports.loadIPC = () => {
const ipcDir = path.normalize(__dirname + '/')
fs.readdirSync(ipcDir).forEach(function (filename) {
if (path.extname(filename) === '.js' && filename !== 'index.js') {
const filePath = path.join(ipcDir, filename)
require(filePath)
}
})
}

22
electron/ipc/system.js Normal file
View File

@@ -0,0 +1,22 @@
const { appExit, appRelaunch, choiceFile, choiceFolder } = require('../apis/base')
const { answerRenderer } = require('./index')
/**
* 退出app
*/
answerRenderer('system.exit', appExit)
/**
* 重启app
*/
answerRenderer('system.relaunch', appRelaunch)
/**
* 选择系统文件夹
*/
answerRenderer('system.choiceFolder', choiceFolder)
/**
* 选择文件文件
*/
answerRenderer('system.choiceFile', choiceFile)

View File

@@ -5,6 +5,7 @@ const storage = require('./storage');
const config = require('./config');
const is = require('electron-is');
const api = require('./api');
const ipc = require('./ipc');
module.exports = () => {
storage.setup();
@@ -16,6 +17,8 @@ module.exports = () => {
autoUpdater.setup();
}
api.setup();
// 加载所有的主进程函数
ipc.loadIPC();
}
function logger () {
@@ -32,4 +35,4 @@ function logger () {
}
return true;
};
};

View File

@@ -17,6 +17,11 @@ export const constantRouterMap = [
name: 'UploadFile',
component: () => import('@/views/file/UploadFile')
},
{
path: 'ipcExample',
name: 'IpcExample',
component: () => import('@/views/file/IpcExample')
},
{
path: 'setting',
name: 'Setting',
@@ -24,4 +29,4 @@ export const constantRouterMap = [
}
]
}
]
]

View File

@@ -1,17 +1,20 @@
import Vue from 'vue';
import antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
import App from './App';
import router from './router';
import Vue from 'vue'
import antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'
import App from './App'
import router from './router'
import { VueAxios } from './utils/request'
import InjectIpc from '@/utils/injectIpc'
Vue.use(antd);
Vue.use(antd)
// mount axios to `Vue.$http` and `this.$http`
Vue.use(VueAxios)
// 全局注入IPC
Vue.use(InjectIpc)
Vue.config.productionTip = false;
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app');
render: h => h(App)
}).$mount('#app')

View File

@@ -0,0 +1,26 @@
const { ipcRenderer: ipc } = window.require('electron')
/**
* 异步调用主函数
* @param ipc
* @param channel
* @param param
* @returns {Promise<unknown>}
*/
const callMain = (ipc, channel, param) => {
return new Promise((resolve) => {
// 声明渲染进程函数, 用于主进程函数回调, 返回数据
// 调用主进程函数
ipc.send(channel, param)
ipc.once(channel, (event, result) => {
resolve(result)
})
})
}
export default {
install(Vue) {
Vue.prototype.$ipc = ipc // 全局注入ipc
Vue.prototype.$callMain = (channel, param) => callMain(ipc, channel, param) // 全局注入调用主进程函数的方法
}
}

View File

@@ -63,6 +63,11 @@ export default {
title: '打开文件夹',
pageName: 'FileOpenDir',
params: {},
},
'subMenu_3' : {
title: 'IpcExample',
pageName: 'IpcExample',
params: {},
}
},
'menu_2' : {

View File

@@ -0,0 +1,45 @@
<template>
<div>
<h3 :style="{ marginBottom: '16px' }">
渲染进程与主进程IPC通信Demo
</h3>
<a-list bordered>
<a-button @click="choiceFolder">选择本地文件夹</a-button>
<div>{{ choiceFolderInfo }}</div>
<a-button @click="choiceFile">选择本地文件</a-button>
<div>{{ choiceFileInfo }}</div>
<a-button @click="getMyLuckNum">摇一个幸运数字</a-button>
<div>{{ luckNum }}</div>
</a-list>
</div>
</template>
<script>
const getMyLuckNum = require('./luckNum')
export default {
data() {
return {
choiceFolderInfo: '',
choiceFileInfo: '',
luckNum: ''
}
},
methods: {
choiceFolder() {
this.$callMain('system.choiceFolder', '我要选择系统的文件夹').then(r => {
this.choiceFolderInfo = JSON.stringify(r)
})
},
choiceFile() {
this.$callMain('system.choiceFile', '我只选择excel文件', ['xlsx', 'xls']).then(r => {
this.choiceFileInfo = JSON.stringify(r)
})
},
getMyLuckNum() {
// 在外部js中调用主进程函数
getMyLuckNum(this, 'CNNN').then(r => this.luckNum = r)
}
}
}
</script>
<style></style>

View File

@@ -0,0 +1,5 @@
function getMyLuckNum(vue, name) {
return vue.$callMain('example.test', name)
}
module.exports = getMyLuckNum