平时总会写markdown,markdown总体语法用起来很方便,但依然有晦涩的地方,好比表格。markdown的表格语法写起来很容易出错,并且每行每列单元格里的内容长短不一编辑器里就很容易乱掉,因此我在写表格时候都是借助Tables Generator来写的,可是这个网站不能保存多个模板,每次写不一样的表格都要把列数,表头信息来回改,很麻烦,因而打算本身照着Table Generator写一个简单的,能保存表头信息的东西出来。先看一哈大体的样子:css
最初在考虑的是要不要写一个差很少的简单的页面,可是我我的不太喜欢总开新的tab来回切换,因此忽然想到能够作成一个简单的桌面应用,想用的时候能够直接从Dock启动,并且Electron有了解过但没实际用过,也能够尝尝鲜,就决定用Electron直接作成一个小应用了。html
在这个"不用脚手架不舒服" + "不用框架不舒服"的时代,搭建工程固然是选择一款靠谱的脚手架了,开发环境 + 打包构建都能经过命令行搞定,极大程度地节省了时间,感谢开源贡献者吧~这里我选择了electron-vue这个模板,基于vue-cli的,初始化项目很简单,直接执行:前端
vue init simulatedgreg/electron-vue my-project
而后根据提示输入完项目名,项目描述,依赖和构建工具(electron-builder
或者electron-packager
)后,一个项目就搭建完成了,进入目录执行:vue
yarn && yarn dev
而后项目就以开发模式运行起来了git
后续的开发工做,若是你的应用对于系统级别的API需求不大,事实上和开发网页的体验并无什么区别。好比我要完成的这个小工具就和开发网页的体验差很少。github
实现的思路比较简单:为表格的每个单元格设置contenteditable
,这样整个表格的内容都是能够随意编辑的,而后再经过MutationObserver监听表格内容的变化,构造出正确的数据结构便可。web
为th和td添加 contenteditable 使其内容能够编辑:vue-cli
<table id="table"> <tbody> <tr> <th class="col-mark"></th> <th data-row="0" :data-col="index" v-title="item.text" v-for="(item, index) in columns" :key="item.key" contenteditable :class="{'active': index === acCol}" ></th> </tr> </tbody> </table>
而后在渲染完成后使用MutationObserver监听变化:markdown
mounted () { this.targetNode = document.getElementById('table') // this.handleMutation是具体处理回调 this.observer = new MutationObserver(this.handleMutation) this.observer.observe(this.targetNode, this.config) }
这里的MutationObserver的配置是{ subtree: true, characterData: true, childList: true }
做用分别是:数据结构
textContent
的修改。核心概念主要就用到了这两个概念,样式上选择了papercss,简单的功能搭配简洁的风格。
表格信息写好以后,最后的功能就是生成对应的markdown内容而后复制到粘贴板了。Electron提供了clipboard API
,直接调用clipboard.writeText
就能把内容写入粘贴板:
import { clipboard } from 'electron' let text = 'xxx' clipboard.writeText(text)
这里复制成功后能够给出一个提示信息,咱们在Electron开发的内容通常是在render进程的,在render进程中能够直接使用HTML5 Notification API来实现提示:
let myNotification = new Notification('Table Generator', { body: 'Copy successfully~' }) setTimeout(() => { myNotification.close() }, 2000)
实际效果为一个两秒后自动消失的提示框:
这里要实现的效果是经过自定义的快捷键删除左侧模板列表中的模板,可是快捷键注册只能在主进程经过globalShortcut
注册,而对于删除行为的响应(二次确认的弹窗)是在渲染进程,因此设计到了主进程和渲染进程的通讯。
渲染进程是主进程中建立的一个BrowserWindow
实例,实例的webContents
属性是对渲染进程的引用,因此主进程能够直接经过webContents
发送事件:
// 建立的渲染进程 mainWindow = new BrowserWindow({ height: 560, minHeight: 450, width: 1000, minWidth: 760, titleBarStyle: 'hiddenInset', show: false, backgroundColor: '#fff' }) // 注册快捷键 globalShortcut.register('Cmd+D', () => { // 直接经过mainWindow.webContents发送事件 mainWindow.webContents.send('del-tpl') })
而在对应的render进程,能够经过ipcRenderer
监听消息:
ipcRenderer.on('del-tpl', () => { // 触发modal弹出 this.$refs['del-btn'].click() })
事实上经过一些简单的配置,就可让你的应用体验更好:
titleBarStyle: 'hiddenInset'
实现(针对Mac系统)show: false
隐藏窗口,在'ready-to-show'
事件触发时手动调用窗口实例的show()
方法,保证窗口渲染完再展现。本次初步的尝试并无用到太多系统级别的API,基本和开发Web页面体验同样,文中提到的API和优化点都是文档上能够找到的,本次实践只是对Electron的一次涉猎,后续能够考虑将各类操做和提示都迁移到原生的API,或者再加入其它功能,不过用来生成markdown内容“初心”已经达到了~
源码在GayHub上,有兴趣的同窗也能够本身安装依赖构建体验一哈,顺便点个star~最后,咱们在招前端开发,欢迎投递简历至hzchenjinghui@corp.netease.com!