electron + vue3 + element-plus + blockly项目搭建与踩坑

目录

项目背景

框架版本

框架的个人理解

项目搭建 

electron搭建

blockly

开发

blockly

踩坑一

吐槽 

踩坑二

解决一

 解决二

electron

路径问题

loadFile和loadURL

BrowserWindow.getAllWindows()


项目背景

笔者之前主要是做后端,前端只了解一点点,用的也是vue2,但是工作需求要去做前端。虽然需求说使用的是vue3,奈何不会ts,vue3当vue2用。¯\_(ツ)_/¯

electron官方文档:简介 | Electron (electronjs.org) 

element-plus官方文档:Button 按钮 | Element Plus (element-plus.org)

blockly中文文档:Blockly 简介 | Blockly 中文文档 (tortorse.com) 

blockly官方文档:Blockly  |  Google for Developers

框架版本

vue:3.2.45

electron:21.3.3

blockly:8.0.5

element-plus:2.3.3

electron-vite:1.0.17

框架的个人理解

electron是一个使用前端三件套搭建桌面应用的框架,本身内容并不复杂,更多的是用来将你写出来的网页与操作系统建立联系,这么说不太严谨,官方一点的话语叫做“深化与操作系统和 Node.js 的集成”,至于页面的具体内容,你使用vue、react等框架都不会有任何影响,因此,在要求不高的情况下,你甚至可以只参照官网文档提供的教程去完成项目的electron框架部分。

blockly是Google提供的一个开源的库,有点类似低代码平台,但是是纯JavaScript开发的,100%客户端,不会与服务器有任何接触,可以用它去做可视化编程软件。

至于element-plus,也是比较常用的一个ui库了,不再过多介绍。

项目搭建 

electron搭建

笔者用的是electron-vite搭建项目,官方文档在这:快速开始 | electron-vite (cn-evite.netlify.app)

 因为是个前端小白,按照官方文档的步骤走的时候出了个糗。跟着官方文档安装electron-vite,然后去创建项目,官方文档里只贴了几种方式的创建语句:

yarn create @quick-start/electron

笔者小白想知道@quick-start/electron里的quick-start是不是项目名,于是将@quick-start换成了test,执行!

yarn create v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...

warning "create-test@1.0.0" has no binaries
[1G[##] 2/2'C:\Users\XXX\AppData\Local\Yarn\bin\create-test' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
error Command failed.
Exit code: 1
Command: C:\Users\XXX\AppData\Local\Yarn\bin\create-test
Arguments:
Directory: C:\Users\XXX\Desktop\test
Output:

info Visit https://yarnpkg.com/en/docs/cli/create for documentation about this command.

???

这一下直接给笔者整蒙了,研究了一下报错信息(然后发现看不懂)。又换回去执行,这次没有任何问题,接着就是和官方文档贴出来的一样,一路往下进行配置,最后运行,畅通无阻。笔者好奇心被勾起来了,正常来讲项目名一定是可以更改的,并且执行创建语句后还有一次提示输入项目名,为什么会有两个项目名?为什么不能改项目名?带着这些疑问笔者询问了做前端的朋友。。。然后就出糗了。。。

@quick-start/electron并不是什么项目名,而是一个模块包!它提供了一个 Electron 项目的基础模板。豁然开朗,难怪执行后还要输入项目名,难怪改了“项目名”后执行报错。如果不想使用这个模板的创建语句应该是下面这样:

npm create my-electron-app-name

这里的my-electron-app-name才是项目名

blockly

blockly两个文档的观感体验都较差,所谓的中文纯机翻,而且文档示例较少,大部分都只有概念介绍。相对而言,中文文档的排版更舒服一点,笔者看的是中文文档,官方文档只瞄过几眼。需要注意的是官方文档也支持中文,笔者贴出来的链接就是中文的文档链接

机翻内容

机翻内容

而且不止是机翻的问题,有些地方介绍含糊不清

还有,整个官方文档的示例代码都是基于纯JavaScript开发,没有其它任何使用框架的示例,这一点非常令人头疼,这年头谁还纯js开发

如果是个人开发,建议不要使用blockly!

开发

开发内容主要是vue+blockly,electron基本只是个项目运行的壳子,只用到了和Windows系统的交互

blockly

踩坑一

blockly有个功能代码生成器,将工作区中的块转换成你想要的代码,按照官方文档的步骤,这只是个三四行代码的小问题,但是折磨了笔者一天半,中间咨询了前端朋友和ChatGPT,最后还是自己去翻源码才试出来了正确写法

官方文档写法:

1. 引入相关语言的生成器,注意要先引入blockly_compressed.js。不同的语言引入不同的js文件,具体参考官方文档

<script src="blockly_compressed.js"></script>
<script src="python_compressed.js"></script>

2. 使用代码生成器

var code = Blockly.Python.workspaceToCode(workspace);

很简单对吧,但是笔者用的是vue,肯定不是这么写的,于是笔者前往百度,得到以下写法

vue写法:

import Blockly from "blockly";
import 'blockly/python';

var code = Blockly.Python.workspaceToCode(workspace);

还是很简单对吧!好!保存!执行!

 (꒪⌓꒪)

笔者随后咨询了ChatGPT,也是这种写法,询问前端朋友,被告知肯定是方法调用错了,报错信息是workspaceToCode未被定义,这个方法肯定不是这种方式调用,但是笔者手上还有一个能正确启动运行的项目,也是这种写法。笔者试过换版本等方法,但就是两个项目一个报错,一个没问题。随后开始研究源码。

成功写法:

import { pythonGenerator } from "blockly/python";

var code= pythonGenerator.workspaceToCode(workspace);

两个写法读者都可以试一下,看一下哪个能正确使用,具体导致报错的原因笔者也不清楚

吐槽 

这个库有点毛病,笔者上周使用下面的写法成功运行之后就没动了,这周一回来一跑又报错,改成上面的写法后又成功了。。。建议读者两个都试一下

踩坑二

在这种情况下——使用el-tabs制作多个el-tab-pane标签页,每个标签页中都注入一个blockly工作空间,各个工作空间之间独立运行,互不干扰,你就会发现出现很莫名其妙的问题,第一个标签页中的工作空间workspace1正常显示,但是当你新增标签页,新增的第二个标签页中的工作空间workspace2是空白(或者只有很小一块的网格空间),点击blockly工具栏也没有任何反应,但是将页面进行任意的大小更改后(包括F12打开控制台、最大化、缩小化、鼠标手动拉动页面调整大小),workspace2的内容都能正常显示,但是当你点进标签页1时,发现刚刚的症状出现在了workspace1中。而不使用el-tabs时,仅仅使用两个div,将两个workspace注入到这两个div的情况下,两个workspace都能正常显示和工作

解决一

笔者在碰到上述问题后,选择将工作空间不放入el-tab-pane中,而是在外面使用v-for循环遍历工作空间,使用v-show去选择显示workspace,主要代码如下(对于tabs的一些增删操作与探讨的内容无关,因此未贴出),但是这种解法还存在bug,详细请看解决二

<script>
export default {
    data() {
        return {
            workspaceList: [], // 工作空间列表,用来注入blockly工作空间
            currentPane: 0, // 当前标签页name值
            editableTabs: [
                {
                    title: '标签页1',
                    name: 0
                }
            ] // 标签列表
        }
    },
    mounted() {
        this.blocklyInject() // 初始化第一个工作空间
    },
    methods: {
        blocklyInject() {
            this.workspaceList[this.currentPane] = Blockly.inject(`blocklyDiv${this.currentPane}`, {
                // blockly工作空间的内容
            })
        }
    }
}
</script>

<template>
    <el-tabs v-model="currentPane">
      <el-tab-pane
        v-for="item in tabs"
        :key="item.name"
        :label="item.title"
        :name="item.name"
      ></el-tab-pane>
    </el-tabs>
    <div
      v-for="tab in tabs"
      v-show="tab.name === currentPane"
      :id="`blocklyDiv${tab.name}`"
      :key="tab.name"
    ></div>
</template>
 解决二

通过解决一的代码可以解决新增的标签页的工作空间不能正常显示和工作的问题,但是在页面中存在不止一个标签页时,选中一个标签页显示,如果页面的大小被改变(与上述问题描述时的操作一样),非当前显示的标签页的工作空间又双叒叕出现了上述问题。感谢这篇文章给我的灵感——2-Blockly工作空间(可变尺寸) - 知乎 (zhihu.com)

解决办法很简单,在合适的地方调用下面这个方法即可(如切换标签页时)

Blockly.svgResize(this.workspace1)

官网描述的此方法功能如下 

但是这个方法能否解决最开始的问题,笔者并未进行尝试,欢迎读者在最开始遇见此问题时直接使用解决二的方法进行尝试,并将结果贴在评论区交流

electron

由于electron框架是运行在Node和浏览器两个环境中的,所以划分出了主进程和渲染进程两个概念,主进程的运行环境是Node,渲染进程是浏览器。笔者项目的需求是通过electron的Node环境进行文件的读写操作,两个进程各有各的操作,这就涉及到electron的进程通信

进程间通信 | Electron (electronjs.org)

没有什么很复杂的东西,按照示例就可以实现。但是如果是读写文件需要注意一点,调用的方法是Node的fs.readFile和fs.writeFile,这两个方法都是异步操作的!如果需要获取数据返回值,可以使用promise封装方法。主要就是搞清楚主进程写哪些东西,渲染进程写哪些东西,然后通过官方提供的api调用进程间的通信就可以了。

读文件操作示例:

main.js(主进程):

async function load() {
  const readF = () => {
    return new Promise((res, rej) => {
      fs.readFile('./code.json', 'utf-8', (err, data) => {
        if (!err) {
          res(data)
        } else {
          rej(err)
          throw err
        }
      })
    })
  }
  const JSONData = await readF()
  return JSONData
}

//创建窗口前加入主进程的监听
app.whenReady().then(() => {
  ipcMain.handle('load', () => load())
  createWindow()
})

preload.js(预加载):

contextBridge.exposeInMainWorld('file', {
      //向渲染进程暴露通知主进程读取文件的方法
      load: () => ipcRenderer.invoke('load')
    })

renderer.vue(渲染进程):

<template>
<button @click="load()">读取</button>
<p v-text="code"></p>
</template>

<script setup>
const code = ref();
async function load() {
  //调用预加载暴露的方法
  const data = await window.file.load()
  code.value = JSON.parse(data)
}
</script>

路径问题

另外,关于在main和preload文件夹下文件中写到的相对路径,都是基于out目录下对应的main和preload下的对应文件,这点需要注意

loadFile和loadURL

loadURL可以加载外部资源,也就是包括网站等非你项目包里的资源

loadFile只能加载包里有的文件

两个方法读取本地资源时都无法识别vue文件,会将内容全部作为文本显示在页面上,只能识别html文件并渲染

BrowserWindow.getAllWindows()

这个方法返回的窗口数组需要注意的是,新创建的窗口是从数组头部插入的,也即是如果你需要实现这种场景:打开一个新窗口并关闭原来的窗口,应该使用

// 在此之前是new BrowserWindow操作
const wins = BrowserWindow.getAllWindows()
wins[1].close()

而不是wins[length - 2].close()

 后续

不要用blockly!不要用blockly!不要用blockly!

这个项目是与其他人合作研发的,架构也是对方提出来的,然后实际开发中发现blockly根本无法满足企业开发要求,正如blockly自己所说的,只适合用来开发面向无编程基础的孩童的教育性项目

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值