BlueRoseNote/07-Other/Node.js/Electron/Vue-cli项目移植Electron-vue的相关经验.md
2023-06-29 11:55:02 +08:00

6.0 KiB
Raw Blame History

移植经验

  1. 使用npm下载所有在vue-cli项目所使用的模块比如element-ui、NProgress之类的。
  2. 将vue-cli项目中src目录下所有文件复制到electron-vue中对应目录。不要直接覆盖main.js因为electron-vue中有一些写法不同了对于这个文件需要自己仔细移植比如 Vue.use(require('vue-electron'))就与vue-cli不同
  3. 运行npm run dev解决报错问题。(主要是因为路径失效造成的问题)

this.$router.push()报错then() undefined

这有可能是因为你使用了动态加载路由也就是在vue-router中使用了vuex,同时夹杂了Electron-vue模板里的东西。在electron-vue模板使用的store/index.js文件中调用了vuex-electron插件而这些插件貌似会与结构起冲突把这些东西删除了就好了。

// import { createPersistedState, createSharedMutations } from 'vuex-electron'

// plugins: [
//   createPersistedState(),
//   createSharedMutations()
// ],

我使用的动态路由是修改自 PanJiaChen/vue-admin-template。该作者也做了个Electron的项目同样是用Electron-vue模板所以相当值得参考。

跨域问题

我一开始也很疑惑为啥electron-vue中为啥没有proxytable。后来发现的确没有必要。如果有只可能是因为你的需求有问题。

vue-cli项目是将打包好的js、html等文件一起放到服务端中之后通过浏览器来浏览。服务端和前端文件是放在一起的。所以为了解决前后端分离的问题才使用跨域转发的方式来解决开发模式需要跨而生成模式就不需要。而Electron开发与生成都需要跨毕竟前端和服务端不在一起。所以也就不存在跨域问题也就不需要ProxyTable了。

我的解决方法是这样: 设置一个config.js作为全局设置文件。在里面设置一个变量用于存储本地服务器ip之后在使用axios编写get与post接口的文件将服务器ip变量加到接口地址前就可以了。例如

export const requestLogin = params => {return axios.post(`/login`,params).then(res => res.data); };

=>

//在config.js中base为127.0.0.1:3000
import {base} from '../config';
export const requestLogin = params => {return axios.post(`${base}/login`,params).then(res => res.data); };

如果需要导出web版本则可以使用process.env.IS_WEB来判断是否为web模式。

静态文件与启动本地服务问题

之前曾想过在electron里直接导入服务端代码来运行服务器但后来发现不行。github上代码都是通过electron(Node.js)的child_process来启动外部服务器的。

这里我使用pm2来启动这样就不需要在程序关闭时关闭服务器了。child_process 老是无法关闭服务器进程,不知道为什么)

let exec = require('child_process').exec;
let server = exec("pm2 start ./bin/www", {cwd: process.cwd()+'/server'});

静态文件可以放再electron目录下的static文件夹中(之后会打包成asar文件)不过因为本人写的app需要定时更新文件且文件类型较杂所以使用本地服务端来管理静态文件。

于是对于项目中的需要显示图片或者其他文件链接就需要加入本地服务器ip地址就像上一节那样。

打包后静态文件失效问题

__dirname是Electron-vue中在webpack中配置的变量对应开发模式与 产品模式时的electron静态文件目录。但如果你使用了一些webpack中没有设置的文件比如字体会出一些问题请参考这个blog https://blog.csdn.net/aa661020/article/details/79757859

关于自定义协议

本人写的app使用了类似QQ的自定义协议来启动自己写的外部程序并传参在electron中为了安全的问题默认把这个功能屏蔽了。electron中应该可以使用protocol来定义协议来解决问题不过我找到了另一种方法那就是直接使用child_process的exec直接用命令行的方式来启动程序。

直接在渲染进程中xxx.vue文件

<script>
  const exec = require('child_process').exec;
  export default {
        methods: {
            exec(row){
                //s为自定义协议的字符串
                let s='xxxxxx';
                let url="test://"+ s;
                
                //test为程序名注意后面有空格第二个参数中提供程序的运行位置具体的可以参考node.js文档。
                exec("test "+url, {cwd: process.cwd()+'/XXXX'});
              }
          }
  }
</script>

不过需要注意在中文windows系统没有修改过默认字符集的浏览器里通过自定义协议来启动程序默认传的是gbk的字符集。而不同系统win10win7字符集是不同的。所以就需要对启动程序进行修改。

关于多条命令启动

因为本人写的App需要更新数据库mysql数据库所以本人使用mysql的命令进行恢复数据。 奇怪的是child_process的exec竟然不支持多条语句。所以这里我就使用了child_process的spawn。

多条命令之间使用&&间隔具体的请参照cmd指南还有别的间隔符比如| &

        let cmd='cd /d C:/Program Files/MySQL/MySQL Server 5.7/bin && mysql -uXXXXX -pXXXXX abcde </managersystem_user.sql && mysql -uXXXXX -pXXXXX abcde </abcde_xxxx.sql';

        cmd+=" && mysql -uXXXXX -pXXXXX abcde < /abcde_routines.sql";

        let child = spawn(cmd, {
            shell: true
        });
        //这里还可以输入新的命令与显示cmd返回内容具体的请参考node.js文档
        child.on('exit', ()=> {
            
        });

关于启动参数

//在主进程中
global.sharedObject = {prop1: process.argv}
//渲染进程中
var remote = require('electron').remote,
arguments = remote.getGlobal('sharedObject').prop1;

console.log(arguments); 

最后推荐一下苏南大叔的blog

里面有关electron的文章很不错 https://newsn.net