Electron结合React和TypeScript进行开发
结合ReactTypeScript进行Electron开发1。electron基本简介
electron是使用JavaScript,HTML和CSS构建跨平台的桌面应用程序。我们可以使用一套代码打包成Mac、Windows和Linux的应用,electron比你想象的更简单,如果把你可以建一个网站,你就可以建一个桌面应用程序,我们只需要把精力放在应用的核心上即可。
为什么选择electron?Electron可以让你使用纯JavaScript调用丰富的原生APIs来创造桌面应用。你可以把它看作是专注于桌面应用。在PC端桌面应用开发中,nwjs和electron都是可选的方案,它们都是基于Chromium和Node的结合体,而electron相对而言是更好的选择方案,它的社区相对比较活跃,bug比较少,文档相对利索简洁。electron相对来说比nw。js靠谱,有一堆成功的案例:Atom编辑器VisualStudioCodeWordPress等等。Node。js的所有内置模块都在Electron中可用。2。快速上手2。1安装React(template为ts)yarncreatereactappelectrondemotstemplatetypescript2。2快速配置React
工程架构
index。html!DOCTYPEhtmlhtmllangenheadmetacharsetutf8linkreliconhrefPUBLICURLfavicon。icometanameviewportcontentwidthdevicewidth,initialscale1metanamethemecolorcontent000000metanamedescriptioncontentBleakselectronappbasereactmetahttpequivContentSecurityPolicycontentdefaultsrcselfunsafeinline;linkrelstylesheethrefPUBLICURLcssreset。csstitleelectronApptitleheadbodynoscriptYouneedtoenableJavaScripttorunthisapp。noscriptbodyhtml
App。tsximportReactfromreactexportdefaultfunctionApp(){return(App)}
index。tsximportReactfromreact;importReactDOMfromreactdomclient;importAppfrom。App;importreportWebVitalsfrom。reportWebVitals;constrootReactDOM。createRoot(document。getElementById(root)asHTMLElement);root。render(React。StrictModeReact。StrictMode);Ifyouwanttostartmeasuringperformanceinyourapp,passafunctiontologresults(forexample:reportWebVitals(console。log))orsendtoananalyticsendpoint。Learnmore:https:bit。lyCRAvitalsreportWebVitals();2。3安装electron
将electron包安装到您的应用程序的devDependencies。npmnpminstallsavedevelectronyarnyarnadddevelectron2。4配置main。js、preload。js和package。json文件
main。js导入app、BrowserWindow模块app控制应用程序的事件生命周期。事件调用app。on(eventName,callback),方法调用app。functionName(arg)BrowserWindow创建和控制浏览器窗口。newBrowserWindow(〔options〕)事件和方法调用同appElectron参考文档https:www。electronjs。orgdocsconst{app,BrowserWindow,nativeImage}require(electron)constpathrequire(path)consturlrequire(url);functioncreateWindow(){Createthebrowserwindow。constmainWindownewBrowserWindow({width:800,窗口宽度height:600,窗口高度title:Electronapp,窗口标题,如果由loadURL()加载的HTML文件中含有标签title,该属性可忽略icon:nativeImage。createFromPath(publicfavicon。ico),stringnativeImage。createFromPath(publicfavicon。ico)从位于path的文件创建新的NativeImage实例webPreferences:{网页功能设置webviewTag:true,是否使用webview标签在一个独立的frame和进程里显示外部web内容webSecurity:false,禁用同源策略preload:path。join(dirname,preload。js),nodeIntegration:true是否启用node集成渲染进程的内容有访问node的能力,建议设置为true,否则在render页面会提示node找不到的错误}})加载应用打包react应用后,dirname为当前文件路径mainWindow。loadURL(url。format({pathname:path。join(dirname,。buildindex。html),protocol:file:,slashes:true}));因为我们是加载的react生成的页面,并不是静态页面所以loadFile换成loadURL。加载应用开发阶段需要运行yarnstartmainWindow。loadURL(http:localhost:3000);解决应用启动白屏问题mainWindow。on(readytoshow,(){mainWindow。show();mainWindow。focus();});当窗口关闭时发出。在你收到这个事件后,你应该删除对窗口的引用,并避免再使用它。mainWindow。on(closed,(){mainWindownull;});在启动的时候打开DevToolsmainWindow。webContents。openDevTools()}app。allowRendererProcessReusetrue;ThismethodwillbecalledwhenElectronhasfinishedinitializationandisreadytocreatebrowserwindows。SomeAPIscanonlybeusedafterthiseventoccurs。app。whenReady()。then((){console。log(qppwhenready);createWindow();})Quitwhenallwindowsareclosed。app。on(windowallclosed,function(){OnmacOSitiscommonforapplicationsandtheirmenubartostayactiveuntiltheuserquitsexplicitlywithCmdQconsole。log(windowallclosed);if(process。platform!darwin)app。quit()})app。on(activate,function(){OnmacOSitscommontorecreateawindowintheappwhenthedockiconisclickedandtherearenootherwindowsopen。if(BrowserWindow。getAllWindows()。length0)createWindow()})Inthisfileyoucanincludetherestofyourappsspecificmainprocesscode。Youcanalsoputtheminseparatefilesandrequirethemhere。
package。json
这时候我们来修改package。json文件。配置启动文件,添加main字段,我们这里也就是main。js文件。如果没有添加,Electron将尝试加载包含在package。json文件目录中的index。js文件。配置运行命令,使用electron:electron。区别于react的启动命令start:reactscriptsstart,安装concurrently:yarnaddconcurrently{。。。main:main。js,配置启动文件homepage:。,设置应用打包的根路径scripts:{start:reactscriptsstart,react启动命令build:reactscriptsbuild,test:reactscriptstest,eject:reactscriptseject,electron:electron。,electron启动命令dev:concurrentlynpmrunstartnpmrunelectron},}
preload。jswindow。addEventListener(DOMContentLoaded,(){constreplaceText(selector,text){constelementdocument。getElementById(selector)if(element)element。innerTexttext}for(constdependencyof〔chrome,node,electron〕){replaceText({dependency}version,process。versions〔dependency〕)}})
此时的工程架构
2。5运行electron项目先yarnstart然后再开一个终端yarnelectron或者是npmrundev
其实我们就可以看出Electron就是一个应用套了一个谷歌浏览器壳子,然后里面是前端页面。2。6打包项目
使用electronpackager依赖:yarnadddevelectronpackager
package。json配置打包命令:package:electronpackager。bleakelectronappplatformwin32archx64overwriteelectronversion18。1。0icon。publicfavicon。ico
配置解释:electronpackager应用目录应用名称打包平台架构x86还是x64架构electron版本图标overwrite如果输出目录已经存在,替换它
然后运行命令:yarnpackage
打包时间慢的话可按照下面两种方式优化:方法1:在执行electronpackager前先运行setELECTRONMIRRORhttp:npm。taobao。orgmirrorselectron方法2:在electronpackager命令行加入参数download。mirrorOptions。mirrorhttps:npm。taobao。orgmirrorselectron(Windowsx64)完整版如下:electronpackager。bleakelectronappplatformwin32archx64overwriteelectronversion18。0。4download。mirrorOptions。mirrorhttps:npm。taobao。orgmirrorselectron
然后运行bleakelectronappwin32x64里面的exe文件就可以了。
3。自动刷新页面
当你用react开发的时候,网页内容会自动热更新,但是electron窗口的main。js中代码发生变化时不能热加载。
安装插件electronreloader:yarnadddevelectronreloadernpminstallsavedevelectronreloader
然后在路口引用插件:constreloaderrequire(electronreloader)reloader(module)
就可以实现electron插件热更新。4。主进程和渲染进程
Electron运行package。json的main脚本的进程称为主进程。在主进程中运行的脚本通过创建web页面来展示用户节面,一个Electron应用总是有且只有一个主进程。
由于Electron使用了Chromium来展示web页面,所以Chromium的多进程架构也被使用到,每个Electron钟大哥web页面运行在它的叫渲染进程的进程中。
在普通的浏览器中,web页面无法访问操作系统的原生资源。然而Electron的用户在Node。js的API支持下可以在页面中和操作系统进行一些底层交互。
ctrlshifti打开渲染进程调试(devtools)
默认打开调试:在启动的时候打开DevToolsmainWindow。webContents。openDevTools()5。定义原生菜单、顶部菜单5。1自定义菜单
可以使用Menu菜单来创建原生应用菜单和上下文菜单。首先判断是什么平台,是mac还是其他:constisMacprocess。platformdarwin创建菜单模板:
其是由一个个MenuItem组成的,可以在菜单项官网API查看。consttemplate〔{role:appMenu}如果是mac系统才有。。。(isMac?〔{label:app。name,submenu:〔{role:about},{type:separator},{role:services},{type:separator},{role:hide},{role:hideOthers},{role:unhide},{type:separator},{role:quit}〕}〕:〔〕),{role:fileMenu}{label:文件,submenu:〔isMac?{role:close}:{role:quit,label:退出}〕},{role:editMenu}{label:编辑,submenu:〔{role:undo,label:撤消},{role:redo,label:恢复},{type:separator},{role:cut,label:剪切},{role:copy,label:复制},{role:paste,label:粘贴},。。。(isMac?〔{role:pasteAndMatchStyle},{role:delete},{role:selectAll},{type:separator},{label:Speech,submenu:〔{role:startSpeaking},{role:stopSpeaking}〕}〕:〔{role:delete,label:删除},{type:separator},{role:selectAll,label:全选}〕)〕},{role:viewMenu}{label:查看,submenu:〔{role:reload,label:重新加载},{role:forceReload,label:强制重新加载},{role:toggleDevTools,label:切换开发工具栏},{type:separator},{role:resetZoom,label:原始开发工具栏窗口大小},{role:zoomIn,label:放大开发工具栏窗口},{role:zoomOut,label:缩小开发工具栏窗口},{type:separator},{role:togglefullscreen,label:切换开发工具栏全屏}〕},{role:windowMenu}{label:窗口,submenu:〔{role:minimize,label:最小化},。。。(isMac?〔{type:separator},{role:front},{type:separator},{role:window}〕:〔{role:close,label:关闭}〕)〕},{role:help,label:帮助,submenu:〔{label:从Electron官网学习更多,click:async(){const{shell}require(electron)awaitshell。openExternal(https:electronjs。org)}}〕}〕根据模板创建menu:constmenuMenu。buildFromTemplate(template)设置菜单:Menu。setApplicationMenu(menu)5。2给菜单定义点击事件
可以通过click属性来设置点击事件5。3抽离菜单定义
创建一个menu。js:const{app,Menu}require(electron)constisMacprocess。platformdarwinconsttemplate〔{role:appMenu}如果是mac系统才有。。。(isMac?〔{label:app。name,submenu:〔{role:about},{type:separator},{role:services},{type:separator},{role:hide},{role:hideOthers},{role:unhide},{type:separator},{role:quit}〕}〕:〔〕),{role:fileMenu}{label:文件,submenu:〔isMac?{role:close}:{role:quit,label:退出}〕},{role:editMenu}{label:编辑,submenu:〔{role:undo,label:撤消},{role:redo,label:恢复},{type:separator},{role:cut,label:剪切},{role:copy,label:复制},{role:paste,label:粘贴},。。。(isMac?〔{role:pasteAndMatchStyle},{role:delete},{role:selectAll},{type:separator},{label:Speech,submenu:〔{role:startSpeaking},{role:stopSpeaking}〕}〕:〔{role:delete,label:删除},{type:separator},{role:selectAll,label:全选}〕)〕},{role:viewMenu}{label:查看,submenu:〔{role:reload,label:重新加载},{role:forceReload,label:强制重新加载},{role:toggleDevTools,label:切换开发工具栏},{type:separator},{role:resetZoom,label:原始开发工具栏窗口大小},{role:zoomIn,label:放大开发工具栏窗口},{role:zoomOut,label:缩小开发工具栏窗口},{type:separator},{role:togglefullscreen,label:切换开发工具栏全屏}〕},{role:windowMenu}{label:窗口,submenu:〔{role:minimize,label:最小化},。。。(isMac?〔{type:separator},{role:front},{type:separator},{role:window}〕:〔{role:close,label:关闭}〕)〕},{role:help,label:帮助,submenu:〔{label:从Electron官网学习更多,click:async(){const{shell}require(electron)awaitshell。openExternal(https:electronjs。org)}}〕}〕constmenuMenu。buildFromTemplate(template)Menu。setApplicationMenu(menu)
然后在main。js中createWindow的方法使用require调用:constcreateWindow(){。。。。。。require(。menu)。。。。。。}5。4自定义顶部菜单
我们可以自定义顶部菜单,通过以下两个步骤进行:先通过frame创建无边框窗口。functioncreateWindow(){constmainWindownewBrowserWindow({。。。。。。frame:false})}然后再通过前端页面布局设置顶部菜单
如果想让顶部菜单支持拖拽,可以加如下css:webkitappregion:drag;5。5在渲染进程中使用主进程方法remote和electron(点击创建新窗口)
我们想要通过remote来使用主进程方法和功能。首先要安装electronremoteyarnaddelectronremote在主进程main。js中配置remote:constremoterequire(electronremotemain)remote。initialize()constcreateWindow(){letmainWindownewBrowserWindow({。。。。。。webPreferences:{网页功能设置。。。。。。nodeIntegration:true,是否启用node集成渲染进程的内容有访问node的能力,建议设置为true,否则在render页面会提示node找不到的错误contextIsolation:false,允许渲染进程使用Nodejs}})remote。enable(mainWindow。webContents)}在渲染进程中使用remote的BrowserWindow:App。tsximportReactfromreact使用electron的功能constelectronwindow。require(electron)使用remoteconst{BrowserWindow}window。require(electronremote)exportdefaultfunctionApp(){constopenNewWindow(){newBrowserWindow({width:500,height:500})}return(AppbuttononClick{openNewWindow}点我开启新窗口button)}
我们想要通过使用electron提供给渲染进程的API:constelectronwindow。require(electron)
然后从electron中提取方法。5。6点击打开浏览器
使用electron中的shell可以实现此功能:importReactfromreact使用electron的功能constelectronwindow。require(electron)使用remoteconst{BrowserWindow}window。require(electronremote)使用shellconst{shell}window。require(electron)exportdefaultfunctionApp(){constopenNewWindow(){shell。openExternal(https:www。baidu。com)}return(AppbuttononClick{openNewWindow}点我开启新窗口打开百度button)}6。打开对话框读取文件6。1读取文件
主进程中的dialog模块可以显示用于打开和保存文件、警报等的本机系统对话框。
因为dialog模块属于主进程,如果我们在渲染进程中需要使用则需要使用remote模块。
App。tsximportReact,{useRef}fromreact使用electron的功能constelectronwindow。require(electron)使用remoteconstremotewindow。require(electronremote)const{BrowserWindow}window。require(electronremote)const{dialog}window。require(electronremote)使用shellconst{shell}window。require(electron)使用fsconstfswindow。require(fs)exportdefaultfunctionApp(){refconsttextRefuseRefHTMLTextAreaElementnull(null)constopenNewWindow(){shell。openExternal(https:www。baidu。com)}constopenFile(){constresdialog。showOpenDialogSync({title:读取文件,对话框窗口的标题buttonLabel:读取,按钮的自定义标签,当为空时,将使用默认标签。filters:〔用于规定用户可见或可选的特定类型范围{name:Images,extensions:〔jpg,png,gif,jpeg,webp〕},{name:Movies,extensions:〔mkv,avi,mp4〕},{name:CustomFileType,extensions:〔js〕},{name:AllFiles,extensions:〔〕},〕})constfileContent:stringfs。readFileSync(res〔0〕)。toString();(textRef。currentasHTMLTextAreaElement)。valuefileContent}return(AppTestbuttononClick{openNewWindow}点我开启新窗口打开百度buttonbuttononClick{openFile}打开文件buttontextarearef{textRef}textarea)}6。2保存文件
保存文件需要使用dialog函数里的showSaveDialogSync,与之前的读取文件所用到的showOpenDialogSync类似:constsaveFile(){constresdialog。showSaveDialogSync({title:保存文件,buttonLable:保存,filters:〔{name:index,extensions:〔js〕}〕})fs。writeFileSync(res,textRef。current?。value)}7。定义快捷键7。1主线程定义
引入globalShortcutconst{app,BrowserWindow,nativeImage,globalShortcut}require(electron)
注册快捷键打印字符串、窗口最大化、窗口最小化、关闭窗口。constcreateWindow(){。。。。。。注册快捷键globalShortcut。register(CommandOrControlX,(){console。log(CommandOrControlXispressed)})globalShortcut。register(CommandOrControlM,(){mainWindow。maximize()})globalShortcut。register(CommandOrControlT,(){mainWindow。unmaximize()})globalShortcut。register(CommandOrControlH,(){mainWindow。close()})检查快捷键是否注册成功console。log(globalShortcut。isRegistered(CommandOrControlX))}将要退出时的生命周期,注销快捷键app。on(willquit,(){注销快捷键globalShortcut。unregister(CommandOrControlX)注销所有快捷键globalShortcut。unregisterAll()})7。2在渲染进程中定义
通过retmote来定义const{globalShortcut}window。require(electronremote)globalShortcut。register(CtrlO,(){console。log(ctrlOispressed。)})8。主进程和渲染进程通讯
在渲染进程使用ipcRenderer,主进程使用ipcMain,可以实现主进程和渲染进程的通讯:
App。tsx。。。。。。importReact,{useState,useRef}fromreactconst{shell,ipcRenderer}window。require(electron)exportdefaultfunctionApp(){stateconst〔windowSize,setWindowSize〕useState(maxwindow)。。。。。。传参constmaxWindow(){ipcRenderer。send(maxwindow,windowSize);if(windowSizemaxwindow){setWindowSize(unmaxwindow)}else{setWindowSize(maxwindow)}}。。。。。。return(buttononClick{maxWindow}与主进程进行通讯,窗口最大化或取消窗口最大化button)}
main。jsconst{app,BrowserWindow,nativeImage,globalShortcut,ipcMain}require(electron)constcreateWindow(){letmainWindow。。。。。。。。。。。。定义通讯事件ipcMain。on(maxwindow,(event,arg){if(argmaxwindow){mainWindow。maximize()}elseif(argunmaxwindow){mainWindow。unmaximize()}})。。。。。。}。。。。。。
原文链接:Electron结合React和TypeScript进行开发bleaka博客园
天热了去哪玩儿呢?不妨看看这里有这么个地方,藏在大山里,绿植茂密,灵山秀水,去时的路百转千回,抵达时视野豁然开朗。仿古的街道和建筑,悠悠然的小桥流水,农家的鸡鸣犬吠,饭时的袅袅炊烟,当地人每逢贵客前来……
经济日报携手京东发布数据东部土特产吸睛又吸金数据来源京东消费及产业发展研究院品牌引领农业高质量发展打造知名农业品牌是农业现代化的重要标志。加快农业品牌建设,能够充分发挥农业品牌对乡村振兴、农业农村现代化发展的……
宋祖儿生图封神了!难怪新剧里戴一个黑框眼镜就能美出圈最近,主打时尚职场的新剧《盛装》一经上线便引起了热议,其中特别出演宋祖儿的新人菜鸟穿搭还被很多网友吐槽不接地气,因为剧中宋祖儿饰演的李娜初进职场穿得很土,所以被同事……
敲诈小米65亿!对中国狂下黑手的国际流氓,究竟有多无耻?新发布的苹果手机受到了人们的追捧,但苹果公司宣布不再提供充电器,如想要得另买,这也让不少人吐槽苹果的嘴脸。然而这种行为放在雷军眼里可是个好机遇,他们推出了苹果手机充电线,在欧美……
学会做一个安静的女人写最暖心的文字,治愈孤寂的心,关注我,温暖你。经历了世事沧桑,看遍了人情冷暖,积累了无数的人生经历之后,早已满身负累。想要活得轻松,就需要停下来,脱离这尘世的喧嚣,……
睡觉前泡脚真的有助于提高睡眠质量吗有一个谚语叫晚上洗脚胜吃补药。谚语是我们几千年流传下来的,是生活经验的总结,就是有道理的。从医学角度讲也是有好处的。中医说足底包括全身所有的穴位。热水会促进我们的血液血流……
黄河上中下游为啥这样分?(把自然讲给你听)来源:人民日报图片来源:黄河水利委员会上游雪山草原,中游千沟万壑,下游田畴连绵黄河浩荡东流,可谓十里不同景、百里不同俗。打开地图,黄河上中游的分界点是内蒙古托……
红红火火鸵鸟园虎虎生威过大年骑鸵鸟、看恐龙、赏表演、尝美食、品年俗,游客尽情享受假期的美好时光。为丰富节日期间群众精神文化生活,营造喜庆祥和的节日氛围,不断满足人民群众对美好生活的需求,春节假期,好想你金……
中国最好喝的9款酒,100纯酿好喝不上头飞天茅台(酱香)rmb:2589纯净、爽口,略显醇甜推荐指数:赖潭(酱香)rmb:26853vol产地:贵州茅台口感:酱香浓郁,回味悠长比肩飞天茅台推荐指数:清花汾……
削骨后遗症?杨幂近照V脸变国字脸,网友吐槽重回嫩牛五方35岁杨幂的脸是肿了么?近日,杨幂在某平台直播的视频曝光,昔日的小V脸变成了国字脸,被网友吐槽重回嫩牛五方。盘点杨幂出道近30年以来,脸的进化之路,看看她到底是削骨……
有一种惊艳叫张天爱的战斗妆,看到成品的瞬间,网友有减肥效果有一种惊艳叫张天爱的战斗妆,看到成品的瞬间,网友:有减肥效果化妆是绝大多数女孩子们都会的一个技能,熟练地掌握化妆技巧能为自己带来很多的好处!而娱乐圈中的女明星们对化妆的依……
本赛季转会后如鱼得水的六大球星,德罗赞暴走,库兹马逆袭变则通,通则久。这句至理名言在NBA的舞台上,同样适用。引援作为可以改变球队战绩的重要手段,一直都深受各支球队青睐。从保罗的加盟让太阳涅槃重生,再到霍勒迪的加盟,助力雄鹿时隔5……