時間:2023-05-26 02:36:01 | 來源:網站運營
時間:2023-05-26 02:36:01 來源:網站運營
使用Electron開發(fā)記事本:electron-vue
去作為項目的基礎模版,而是在github上著了一個加了webpack
功能的模版,輸入以下命令開始:git clone git@github.com:szwacz/electron-boilerplate.git life-memory
v7.1.7
看看是否可以正常運行,這里為了避免因為網絡問題導致下載失敗就直接用cnpm
進行安裝了。src/menu
目錄下,我們要做兩件事,一是為Mac系統(tǒng)的菜單騰出第一個位置,二是補充自己需要的菜單項。下面是我的菜單項定義:// file_menu_template.js?import { dialog } from 'electron'import log from 'electron-log'?export const fileMenuTemplate = { label: '文件', submenu: [ // { // label: '新建', // accelerator: 'CmdOrCtrl+N' // }, { label: '打開', accelerator: 'CmdOrCtrl+O', click: openFile }, { type: 'separator' }, { label: '保存', accelerator: 'CmdOrCtrl+S', click: saveFile }, { label: '另存為', accelerator: 'CmdOrCtrl+Shift+S', click: saveAsFile } ]}?export const macAppMenuTemplate = { label: '生活記', submenu: [ { label: '退出', role: 'quit' } ]}?/** * 打開文件 * @param {MenuItem} menuItem 菜單項 * @param {BrowserWindow} browserWindow 渲染進程窗口 * @param {Event} event 事件 */function openFile(menuItem, browserWindow, event) { dialog.showOpenDialog(browserWindow, { title: '打開文件', filters: [ { name: 'Markdown 文件', extensions: ['md', 'markdown'] }, { name: '文本文件', extensions: ['txt'] } ], properties: ['openFile'] }).then(dialogRes => { if (!dialogRes.canceled) { // 向當前獲取焦點的窗口發(fā)送事件 if (browserWindow) { browserWindow.webContents.send('lm-open-file', dialogRes.filePaths) } } }).catch(e => { log.error(e) })}?/** * 保存文件 * @param {MenuItem} menuItem 菜單項 * @param {BrowserWindow} browserWindow 渲染進程窗口 * @param {Event} event 事件 */function saveFile(menuItem, browserWindow, event) { if (browserWindow) { browserWindow.webContents.send('lm-save-file') }}?/** * 另存為 * @param {MenuItem} menuItem 菜單項 * @param {BrowserWindow} browserWindow 渲染進程窗口 * @param {Event} event 事件 */function saveAsFile(menuItem, browserWindow, event) { if (browserWindow) { browserWindow.webContents.send('lm-save-as-file') }}?
因為第一個位置暫時也不需要添加其他內容,所以我就沒有將其拆分出去,而是和文件菜單放在一個文件里了。寫這篇文檔時項目已經完成,所以這個文檔的代碼中會包含一些現(xiàn)在用不到的代碼,見諒見諒~
// edit_menu_template.js?export const editMenuTemplate = { label: "編輯", submenu: [ { label: "撤銷", accelerator: "CmdOrCtrl+Z", click: undo }, { label: "重做", accelerator: "Shift+CmdOrCtrl+Z", click: redo }, { type: "separator" }, { label: "剪切", accelerator: "CmdOrCtrl+X", selector: "cut:" }, { label: "復制", accelerator: "CmdOrCtrl+C", selector: "copy:" }, { label: "粘貼", accelerator: "CmdOrCtrl+V", selector: "paste:" }, { label: "全選", accelerator: "CmdOrCtrl+A", click: selectAll } ]};?/** * 選擇全部 * @param {MenuItem} menuItem 菜單項 * @param {BrowserWindow} browserWindow 渲染進程窗口 * @param {Event} event 事件 */function selectAll(menuItem, browserWindow, event) { if (browserWindow) { browserWindow.webContents.send('lm-select-all') }}?/** * 撤銷 * @param {MenuItem} menuItem 菜單項 * @param {BrowserWindow} browserWindow 渲染進程窗口 * @param {Event} event 事件 */function undo(menuItem, browserWindow, event) { if (browserWindow) { browserWindow.webContents.send('lm-undo') }}?/** * 重做 * @param {MenuItem} menuItem 菜單項 * @param {BrowserWindow} browserWindow 渲染進程窗口 * @param {Event} event 事件 */function redo(menuItem, browserWindow, event) { if (browserWindow) { browserWindow.webContents.send('lm-redo') }}?
編輯菜單里面基本上都是對文檔內容的快捷操作。// help_menu_template.js?import { app, shell } from "electron";import jetpack from "fs-jetpack";?const appDir = jetpack.cwd(app.getAppPath());const manifest = appDir.read("package.json", "json");?export const helpMenuTemplate = { label: '幫助', submenu: [ { label: '學習Markdown語法', click: function (item, focusedWindow) { // 打開外部文檔 shell.openExternal('https://www.runoob.com/markdown/md-tutorial.html') } }, // { // label: '幫助' // }, { label: '關于', submenu: [ { label: '版本 v' + manifest.version, enabled: false } // { // label: '更新記錄' // } ] } ]}?
幫助菜單中則是將應用的版本號顯示出來,另外還有一個開發(fā)時顯示的菜單,那個菜單只需要去掉退出應用的菜單項即可。background.js
中,我們需要將新增的菜單定義加入,并稍微修改一下邏輯,讓Mac系統(tǒng)下的菜單列表前面增加一個占位的菜單。import { devMenuTemplate } from "./menu/dev_menu_template";import { editMenuTemplate } from "./menu/edit_menu_template";import { macAppMenuTemplate, fileMenuTemplate} from "./menu/file_menu_template";import { helpMenuTemplate } from "./menu/help_menu_template";?const setApplicationMenu = () => { const menus = [fileMenuTemplate, editMenuTemplate, helpMenuTemplate]; if (process.platform === "darwin") { menus.unshift(macAppMenuTemplate); } if (env.name === "development") { menus.push(devMenuTemplate); } Menu.setApplicationMenu(Menu.buildFromTemplate(menus));};
此時運行程序,我們定義的菜單就會如期顯示出來,接下來要讓程序對用戶點擊菜單項做出響應,則需要在菜單定義中定義click函數
,普通的菜單點擊,我們只需要將事件發(fā)送到當前聚焦的窗口,讓它去處理這個事件即可。ipcRenderer
去獲取,這一點官方文檔已經講得很詳細了,我就不再細說了。electron-log
可以使用。我的用法比較簡單,就在主線程中修改了日志記錄的格式,后面因為全局共享一個實例,所以其他地方就不用去修改配置了,直接引入這個包即可。import log from "electron-log";?// 修改日志記錄的格式log.transports.console.format = "[{h}:{i}:{s}.{ms}] [{level} {processType}] ? {text}";log.transports.file.format = "[{y}-{m}-q9v2uis {h}:{i}:{s}.{ms}] [{level}] {text}";log.debug("path of user data: ", app.getPath("userData"));
在啟動時我還去打印了一下用戶數據的存放位置,方便以后排查問題。CodeMirror
這個插件,引入的時候還是遇到了一些問題的,下面是我的解決方案:import CodeMirror from "codemirror/lib/codemirror";import "codemirror/mode/markdown/markdown";?this.editor = CodeMirror.fromTextArea( document.getElementById(textareaId), editorOptions );
到這一步還是正常的,可當我要引入它的CSS文件時,它就報錯了,我也不知道為什么。但最后想出了一個解決辦法,就是把css文件在html中引入:<!-- app/app.html -->?<link rel="stylesheet" href="../node_modules/codemirror/lib/codemirror.css">
這樣做之后基本上就沒什么問題了,關于記事本的代碼其實很簡單,邏輯也不復雜,就不貼出來獻丑了。async/await
了~cnpm i sass node-sass sass-loader --save-dev
安裝之后,找到build/webpack.base.config.js
,在rules
中添加:{ test: //.scss$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'sass-loader' } ] }
這樣就可以解析scss文件了。1024x1024.png
的圖標之后,還需要為windows平臺生成.ico
格式的圖標,此時我們可以在https://www.easyicon.net/language.en/covert/這個網站去轉換。.icns
的圖標則沒有那么簡單,因為icns格式并不是一個圖標,而是包含不同分辨率圖標的集合,我們需要一個一個的生成然后再去轉換。我就填了這個坑,我在剛剛的網站把轉換好的一張icns格式的圖片放到項目中打包,結果打包后的應用是沒有圖標的!轉換icns并沒有網站可以幫我們做,我們只能在mac電腦中敲命令來做。具體可以參考這個博客,需要注意的是剛開始創(chuàng)建的目錄,后面的
.iconset
不能省,前面的名字可以隨便起。resources
目錄下的圖標文件即可。packages.json
中,恰好我用的這個模版里面的打包工具就是它,我們只需要在build
下面加上下面的配置即可關聯(lián)自己定義的文件格式了。"fileAssociations": [ { "ext": "md", "name": "Markdown 文件", "role": "Editor" }, { "ext": "markdown", "name": "Markdown 文件", "role": "Editor" }, { "ext": "txt", "name": "文本文件", "role": "Editor" } ],
關聯(lián)之后,程序只是虛有其表,因為我們并沒有真正去處理傳來的文件,所以下一步就是接收文件路徑。在這一步自己也爬了一個又一個坑,都是血和淚的教訓啊。。。open-file
事件的,而Windows則是通過進程對象來獲取文件路徑。// background.js?// 外部文件路徑let preFilePath = ''?app.on('will-finish-launching', () => { log.debug('will-finish-launching')? // 打開文件事件(MacOS有效) app.on("open-file", (e, filePath) => { log.debug("open-file: ", filePath);? const fw = BrowserWindow.getFocusedWindow(); if (fw) { fw.webContents.send("lm-open-file", [filePath]); } else { preFilePath = filePath } });? // 檢查進程是否含有參數(Windows有效) if (process.platform ==='win32' && process.argv.length >= 2) { log.debug('process argv:', process.argv)? // windows系統(tǒng)當沒有路徑參數時這個位置默認有個.,需要加以判斷 preFilePath = process.argv[1] === '.' ? '' : process.argv[1] }})?mainWindow.once('ready-to-show', () => { log.debug('ready-to-show') mainWindow.show()? // 檢查是否存在需要直接打開的文件,有的話就直接打開 if (preFilePath) { mainWindow.webContents.send('lm-open-file', [preFilePath]) } })
其中,在app的will-finish-launching
事件中才開始監(jiān)聽文件打開事件,也是官方文檔上面建議的:關鍵詞:記事,使用