断断续续写了个把月,终于在昨天完成了初版…
一款帮助网络写手更方便地进行小说创做的PC软件,目前支持 OSX/Windowsjavascript
名字灵感来自于杜甫的一首诗,前两句是:html
《寄李十二白二十韵》昔年有狂客,号尔谪仙人。前端
笔落惊风雨,诗成泣鬼神。vue
对于名字,要感谢下@蓝色java
预览的话,能够去官网看node
做为个人第一款商业性(虽然才卖出去一个,仍是朋友捧场…)产品,我投入了不少精力。并且,重要的还在后面,那就是运营。webpack
怎么让得让更多的人知道而且去使用它?直觉告诉我,这将是比写代码还要难的事情...git
主要用到了Electron-Vue这个框架,让我不用花时间去琢磨配置Webpack和Electron,上来就直接开发。感谢开源社区!github
歪个楼:我对Wepback的见解就是,笼统的了解下运行原理就好了,现成而且配置好的Webpack模板直接用,遇到特殊需求,查文档,查Google知道怎么改便可。
开发要求你比较熟悉Vue和Node,这里不会讲基础的东西,讲基础知识的除了官方文档,网上有更多相关文章可供选择。web
首先,我遇到了:dev模式没问题,打包后空白页的问题?
若是你刚刚生成项目,什么都没有动的话,那就多是Webpack在打包时,把Vue当成了外部文件没有打包进去。
代码在:webpack.renderer.config.js
注释掉...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d))
便可
而后,又遇到了多窗口的需求:
开始没思路,由于多窗口和通常前端开发时遇到的多路由,多Tab还不是一回事儿。后来经人指点,才明白其实多窗口挺简单的...
咱们先观察生成的代码模板中,主窗口是怎么生成的:
let mainWindow; //主窗口变量 const winURL = process.env.NODE_ENV === 'development' ? `http://localhost:9080` : `file://${__dirname}/index.html` // 设置URL或者文件,毕竟Electron App其实运行在Chromium中 mainWindow = new BrowserWindow(options) // new 一个窗体对象,同时传一些参数 mainWindow.loadURL(winURL) // 加载URL,加载以后,窗口就会被显示出来。
那么,咱们依葫芦画瓢,第二个窗口就能够这么写
let secondWindow; const modalPath = process.env.NODE_ENV === 'development' ? 'http://localhost:9080/#/showOutline' : `file://${__dirname}/index.html#showOutline` // 的确比较简单... secondWindow = new BrowserWindow(options) secondWindow.loadURL(modalPath)
PS: 这里提醒下vue-router不要设置成history模式。缘由在文档里看到过,忘了,想知道就去查文档 :p
多窗口下的Vuex异常:
开发多窗口时并无意识到vuex存在问题,后面发现数据怎么都对不上,而后排查问题时发现,两个窗口的state(状态)并不一样步,即:
当你在打开窗口B时,此时两个窗口的Vuex数据时一致的,但一旦你的B窗口的数据状态发生变化,其并不能反映到窗口A里。为何不行,其实也很好理解。
歪个楼:说下我对Vuex实现原理的理解。之前刚开始学习Vue尚未学Vuex时,当时我解决多组件(非父子)之间的通信方式除了利用父组件作中间人(event bus)外,还试过维护一个全局JSON(好比共用一个store.js),而后其余组件都能访问及操做。后来学了Vuex,发现它的工做方式和我想的差很少。(固然,我并无去看源码,它真正的实现方式是什么。但直觉告诉我应该是这样没错了!)
让我反问一句:为何两个窗口之间的数据能一直同步?
解决方法: 我结合了Electron文档中提到的两种方式:ipc通信
和在主进程维护全局变量
PS: 经人点拨,ipc通信的实现利用了浏览器的postMessage
接口(话说这个API,以前还真没听过说...)
在Vue中本身实现富文本编辑器:输入框的双向绑定和自动聚焦(auto focus)
还有个不算是Electron,只能说是Vue方面的问题。原本写这个项目时就没打算来本身实现富文本编辑器,本着能用开源就用开源的原则,在项目里测试了一些开源的编辑器,发现或多或少都有些问题,后来一琢磨,反正这个项目的富文本编辑器需求不复杂,就本身实现一个好了。
编辑器的输入框,我使用的HTML属性contenteditable
来实现。
编辑器组件的双向绑定和自动聚焦的细节参考这篇文章
用户数据的本地存储我用了lowdb:
本质就是经过node
的fs
模块来操做本地JSON
文件,只不过它比咱们本身实现的要优雅,可靠多了
而后有个需求是,当触发某种条件时,保存对应的变量:
// 当用户点击Button A db.set('a',111).write(); // 当用户点击Button B db.set('b',222).write();
此时,若是用户点击了Button A,不只a
数据会更新,b
数据也会更新,反之一样。
这不是lowdb
的问题,由于我单独测试过,点击Button A并不会致使其余set函数调用!
因此这应该算是一个奇怪的问题吧。
利用ipcRenderer监听通讯时,若是在listener内使用了异步:
ipcRenderer.on('delete', () => { // 异步这里特指setTimeout setTimeout(() => { // 不知为什么,_this.remove会调用屡次(但发现ipcMian.send只被调用了一次!) _this.remove(this.nodeWasRightClicked, this.dataWasRightClicked); }, 0); });
另外: 打包软件时也遇到了不少问题,但最终都经过Google解决掉了,因此这里不复述了(所谓面向Google编程)
其余问题后续会继续补充,欢迎持续关注!