electron+vue全家桶开发包含(心得,遇见的坑,解决办法等)

简介: electron+vue全家桶开发包含(心得,遇见的坑,解决办法等)

简单介绍


目前网上有好多关于electron相关的文章,但是本人在开发的时候发现,网上大部分文章可以说是千篇一律,没有真正的痛点解析啥的很无语 ,好多的问题都需要自己去找、去试,这无异于加大了开发成本与学习成本,所以本篇博客会从electron 的api 到 electron +vue 组合式开发到 打包 及开发过程中遇见的问题分门别类的进行说明, 当然在最后的文末我会将我写的 electron + vue全家桶的git开源项目附上,需要的话就去git 吧


electron基础 (基础补习)


官方文档


什么是electron


Electron 是一个框架,可以让您使用 JavaScript, HTML 和 CSS 创建桌面应用程序。 然后这些应用程序可以打包在macOS、Windows和Linux上直接运行,或者通过Mac App Store或微软商店分发。 通常,您使用每个操作系统特定的本地应用程序框架为操作系统 (OS)创建一个桌面应用程序。 Electron 可以在使用您已经知道的技术后写入您的应用程序。


electron 的两个进程(重点)


electron 主要分为两个进程 分别是主进程和渲染进程

  • 主进程 通过创建浏览器窗口实例来创建 个网页。 每一个 浏览窗口 实例在其渲染过程中运行网页. 当一个 BrowserWindow 实例被摧毁时,对应的渲染过程也被终止。
    -主进程 管理所有 个网页及其对应的渲染过程。
    渲染进程 只能管理 个相应的网页。 在一个渲染过程中崩溃不会影响其他渲染过程。
    渲染进程 通过IPC 与主进程通信 在网页上执行GUI操作。 由于安全考虑和可能的资源泄漏,直接从渲染器过程中调用与本地GUI有关的API受到限制。
    流程之间的通信可以通过进程间通信模块进行: ipcMainipcRenderer
    接下来分别说一下渲染进程和主进程
/* 个人认为electron的难点的主要就是 主进程和渲染进程之间的通信, 
  其次就是关于electron的api了,接下来我们一起来揭开这个小东西的神秘面纱吧!! 
 */
• 1
• 2
• 3

创建主脚本文件

主脚本指定了您将运行主进程的 Electron 应用程序的入口点(通常情况下是 main.js 文件)【后续代码结构中会有示例说明】。 通常,在主进程中运行的脚本控制应用程序的生命周期,并显示图形用户界面及其元素。 执行本机操作系统交互,并在网页中创建渲染程序。 Electron 应用程序只能有一个主流程。

主脚本可以如下所示:

1.   const { app, BrowserWindow } = require('electron')
    2.  
    3.   function createWindow () {
    4.    const win = new BrowserWindow({
    5.      width: 800,
    6.      height: 600,
    7.      webPreferences: {
    8.        nodeIntegration: true
    9.      }
    10.   })
    11. 
    12.   win.loadFile('index.html')
    13.   win.webContents.openDevTools()
    14. }
    15. 
    16. app.whenReady().then(createWindow)
    17. app.on('window-all-closed', () => {
    18.   if (process.platform !== 'darwin') {
    19.     app.quit()
    20.   }
    21. })
    22. 
    23. app.on('activate', () => {
    24.   if (BrowserWindow.getAllWindows().length === 0) {
    25.     createWindow()
    26.   }
    27. })
    28. 

这段代码说的是啥嘞 😮😮

  1. 第1行:为了管理您应用程序的生命周期事件,以及创建和控制浏览器窗口,您从electron软件包导入了appBrowserWindow模块 。
  2. 第 3 行:在此之后,您定义一个函数,该函数创建一个 新的浏览窗口 启用了节点集成,将index.html文件加载到此窗口中(第 12 行,稍后我们将讨论该文件),并打开开发人员工具(第 13 行)。
  3. 第 16 行:你通过调用 createWindow方法,在 electron app 第一次被初始化时创建了一个新的窗口。
  4. 第 18 行:您添加了一个新的侦听器,当应用程序不再有任何打开窗口时试图退出。 因为操作系统 窗口管理行为 ,此监听器在 macOS 上是一个禁门。
  5. 第 24 行:您添加一个新的侦听器,只有当应用程序激活后没有可见窗口时,才能创建新的浏览器窗口。 例如,在首次启动应用程序后,或重新启动已在运行的应用程序。

渲染进程是啥呢 ?? 😒😒

所谓的渲染进程说白了就是你写的html 页面 这不用过多的浪费口舌了 , 后面的实例中会用到,只要有前端基础的 童鞋都会掌握滴


electron API


如果 要在两个 进程中访问Electron Api ,首先需要引入他包含的模块

const electron = require('electron')

若要创建一个窗口,需要调用 ·浏览窗口· 类,并且只能在主进程中使用:

const { BrowserWindow } = require('electron')
   const win = new BrowserWindow()

若要从渲染器调用主流程,则需要使用 IPC 模块:

// 在主进程中
  const { ipcMain } = require('electron')
  ipcMain.handle('exper-action', (evidence, ...args) =>
    // ... 代表渲染器操作
  })
// 在渲染过程中
  const { ipcRenderer } = require('electron') 
  ipcRender.invotrake('exper-action', ...args)

如何在渲染进程中通讯主进程


我们发现在上面的代码中 通讯的操控主要在主进程 ,通过主进程来控制渲染进程,然后渲染进程会将把响应的事件返回到主进程然后在对我们的页面进行操作 ,接下来我们按照这种思路写一个关于自定义窗口放大缩小关闭的代码吧!! 感受下 😜😜😜

效果如图

20201130174647747.png


先看下我的项目目录结构吧

20201130175457244.png

代码书写

// 渲染进程代码如下 
  <template>
  <el-row>
    <el-col :span="24">
      <div class="grid-content bg-purple-dark">
        <!-- <el-button class="btnOut" @click="handleOutWeb" type="text">操作说明</el-button> -->
        <div class="rightEdit">
          <i title="最小化" class="el-icon-minus" @click="min"></i>
          <i :title="title" :class="changeClass" @click="max"></i>
          <i title="关闭" class="el-icon-close" @click="close"></i>
        </div>
      </div>
    </el-col>
  </el-row>
</template>
<script>
let ipcRenderer = require('electron').ipcRenderer;
export default {
  name: "Navbar",
  data() {
    return {
      changeClass: "el-icon-full-screen",   // el-icon-copy-document  最小化窗口
      title: "全屏"
    };
  },
  methods: {
    min(){
      //发送最小化命令
       ipcRenderer.send('window-min');
    },
    max(){
         //发送最大化命令
        ipcRenderer.send('window-max');
        if (this.changeClass === 'el-icon-full-screen') {
           this.changeClass = 'el-icon-copy-document'
           this.title ="最小化"
        }else{
          this.changeClass = 'el-icon-full-screen'
           this.title ="全屏"
        }
    },
    close(){
          //发送关闭命令
        ipcRenderer.send('window-close');
    }
  }
};
</script>
<style lang="scss" scoped> ....
</style>

关于css的代码我就不写了 , 自己去git 上拿吧 https://gitee.com/ruochengflag/mint-video/tree/host/ 在host 分支上哦!

在上面的代码中我们可以看到当我点击minmaxclose 三个按钮时 会通过 ipcRenderer.send 将指令发送到主进程中 ,在主进程中进行判断 , 接下来我们看下主进程中是如何写的嘞

// 在main 文件夹下的 index.js 中 
//引入
 let ipcMain = require('electron').ipcMain;
// 通过命令进行判断 
//接收最小化命令
ipcMain.on('window-min', function() {
  mainWindow.minimize();
})
//接收最大化命令
ipcMain.on('window-max', function() {
  if (mainWindow.isMaximized()) {
      mainWindow.restore();
  } else {
      mainWindow.maximize();
  }
})
//接收关闭命令
ipcMain.on('window-close', function() {
  mainWindow.close();
})

OK , 到目前为止核心代码就 ok 了 , 接下来就是细节处理了

第一点 去除系统自带的导航

将主进程中添加 frame : false;

mainWindow = new BrowserWindow({
    height: 700,
    useContentSize: true,
    maximizable: false, // 默认不能最大化
    width: 1000,
    // resizable: false,
    frame: false,  // 去除自带导航 
    show: false //消除启动时白屏 , 如果想做启动页效果的话会用到
  })

第二点 可拖拽区域

当我们写完自定义导航时会发现窗口无法拖拽 , 啥原因呢?

应用程序需要在 CSS 中指定 -webkit-app-region: drag 来告诉 Electron 哪些区域是可拖拽的

在可拖拽区域内部使用 -webkit-app-region: no-drag 则可以将其中部分区域排除

拖动行为可能与选择文本冲突。 例如, 当您拖动标题栏时, 您可能会意外地选择标题栏上的文本。 为防止此操作, 您需要在可区域中禁用文本选择

我们可以添加如下代码来解决

.titlebar {
  -webkit-app-region: drag;
  -webkit-user-select: none;
}

好了 到目前为止第一种通讯方式已经解决了 , 我们会发现这种通讯方式有些麻烦, 难道所有的通讯都这样解决吗 ?

很心累啊 !!!不要着急 我们还有 第二种 解决办法

第二种通讯方式

在这里只说核心代码 ,其他的问提如 隐藏系统导航 ,拖拽的实现解决办法通第一种哦!!!

第二种方法只需要在渲染进程进行修改就可以了 , 我们无需在去主进程修改代码

<template>
  <el-row>
    <el-col :span="24">
      <div class="grid-content bg-purple-dark">
        <!-- <el-button class="btnOut" @click="handleOutWeb" type="text">操作说明</el-button> -->
        <div class="rightEdit">
          <i title="最小化" class="el-icon-minus" @click="minimizeWin"></i>
          <i :title="title" :class="changeClass" @click="maximizeWin"></i>
          <i title="关闭" class="el-icon-close" @click="closeWin"></i>
        </div>
      </div>
    </el-col>
  </el-row>
</template>
<script>
import { remote } from "electron";
export default {
  name: "Navbar",
  data() {
    return {
      changeClass: "el-icon-full-screen",
      title: "全屏"
    };
  },
  methods: {
    minimizeWin() {
      remote.getCurrentWindow().minimize();
    },
    maximizeWin() {
      // 如果已处于最大化则恢复
      if (remote.getCurrentWindow().isMaximized()) {
        remote.getCurrentWindow().restore();
        this.changeClass = "el-icon-full-screen";
        this.title = "全屏";
      } else {
        remote.getCurrentWindow().maximize();
        this.changeClass = "el-icon-copy-document";
        this.title = "向下还原";
      }
    },
    closeWin() {
      remote.getCurrentWindow().close();
    }
  }
};
</script>
<style lang="scss" scoped>
...
</style>

在这里我们主要通过引入 remote 来进行通讯就可以了, 无需其他操作哦 ! 代码在master 分支自己自行下载。


在使用 Element-ui 的时候Table无法正常显示


在使用Electron-vue搭配使用Element-ui的时候, 在使用Table表格的时候, 会出现页面一片空白, 使用F12进行审查元素的时候,表格的高度为0,而下面的tbody下面也是只是渲染了几个tr空标签,而自己也是找了好久的问题

解决问题

打开/webpack.renderer.config.js文件搜索whiteListedModules

//let whiteListedModules = ['vue'] 
//将这行修改为下面的的内容
let whiteListedModules = ['vue', 'element-ui']

再次运行就好了


electron 如何打开外部链接 【点击连接时在默认浏览器打开链接】


关于打开默认浏览器 , 通常情况下我们 会用原声js 的方法 window.locationg.herf 或者 open等方法来打开,但是在electron 中这种方法是不起作用滴是不是很抓狂 , 其实也很好解决

我们需要


import { remote , shell } from "electron";
// 点击事件 
handleOutWeb(){
shell.openExternal(
       "https://www.baidu.com"
      );
}

这样就可以了

好了到目前为止 关于electron 的部分内容已经完事了 ,

实力有限有好多地方没有在这里写 比如:在electron 中无法打开接口返回的视频链接 , 会返回403 , 这个问题 可以在 我的另一个开源项目中找到https://gitee.com/ruochengflag/mint.git, 在这里,master分支是模板分支 可以直接进行二次开发 , mint-video分支是视频分支 , 有时间就写一下, 目前还在更新中!

如果你也在做相关的项目欢迎交流下哈,


electron +vue全家桶 + element-ui 项目搭建

新建项目


  1. 初始化项目

electron-vuevue-clielectron 结合的项目,比单独使用 vue 构建起的 electron 项目要方便很多.

打开cmd,新建一个项目,我使用的是 electron-vue,输入以下命令:

vue init simulatedgreg/electron-vue my-project

my-project就是我们自己取的项目名。

安装elementui

npm install element-ui -s

然后在main.js文件中全局引入,打开 src/renderer/main.js

import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(Element)


ok 搭建完成 ,

tips:补充一点:

如果你运行项目时 ,没有打开页面也没有报错, 而是显示项目目录, 这种情况下,应该是你的eslint 语法校验的问题,你可以吧eslint 语法校验的规则注释了 ,就可以了 , 但是如果安装的时候不同意elslint 的话好像也会报错 ,不知道为啥, 自己尝试吧。

创作不易给个赞哇!!!!!

相关文章
|
1月前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
7天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
1月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
41 1
vue学习第一章
|
1月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
30 1
|
1月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
38 1
vue学习第四章
|
1月前
|
JavaScript 前端开发 开发者
Vue是如何劫持响应式对象的
Vue是如何劫持响应式对象的
29 1
|
1月前
|
JavaScript 前端开发 API
介绍一下Vue中的响应式原理
介绍一下Vue中的响应式原理
32 1
|
1月前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
|
1月前
|
JavaScript 前端开发 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
1月前
|
存储 JavaScript 前端开发
介绍一下Vue的核心功能
介绍一下Vue的核心功能