自己动手用electron+vue开发博客园文章编辑器客户端【一】

于是动手重新搞这个东西 这次用Vue+electron来搞,算是技术的主流了 先把搞这个东西的心得写出来,希望大家不吝赐教。 界面 截几个图给大家看看, 列表界面: 文章编辑的界面: 功能 博客登录(引入博客园的登录画面,使用官方提供的登录机制) 文章列表(可以检索到你博客园内所有的随笔文章,支持分页,支持文章分类) 修改文章(你博客园内所有的历史随笔文章,都可以用此工具编辑修改) 新增文章(从无到有撰写一篇新的随笔文章,支持保存为草稿) 截图工具截图后直接黏贴到编辑器中(QQ截图、微信截图,直接黏贴到编辑器中) 图片拖拽到编辑器中自动上传 插入公式、插入地图、插入表情、插入表格、插入音乐、插入代码...一应俱全; 纯客户端,直接与博客园服务端通信(没有任何自建服务,不采集用户任何信息) 新版本升级提醒功能; 开源,开源地址:https://gitee.com/xland/cnblogs 操作系统兼容苹果和windows,下载地址:https://gitee.com/xland/cnblogs/releases 搭建环境 这个程序用到了electron和vue 链接这两个东西的桥梁是electron-vue 建议大家给个star,有这么个工具真的能省很多力气(有钱的捧个💰场,没钱的捧个✨场) 用npm工具初始化环境的命令为: 1 2 3 4 5 npm install -g vue-cli vue init simulatedgreg/electron-vue cnblogs51 cd cnblogs51 npm install npm run dev 几行命令执行完,一个默认的模板画面就启动起来了; 我们简单介绍一下electron-vue 我们知道vue有hot-reload的能力, 就是你改了什么代码,马上能在界面上表现出来,非常有利于调试; electron-vue也有这个能力 为了做到这一点,他在你的开发机上起了http的服务; 然而你发布出来的程序,启动的时候,并没有在客户机上也开一个http的服务; 也就是说,开发机上调试程序,界面访问的是http://.......... 客户机上,运行程序界面加载的事:file://......... 工程简述 他src目录下,有两个子目录,一个是main;一个是renderer 之所以这样分目录,跟electron的工作原理有关系 electron与nwjs不同, nwjs把nodejs里的v8和chrome浏览器里的v8整合到一起了,可以直接在网页JS里访问nodejs的库 electron并没有这么做,它分两个主要进程,一个主进程,一个渲染进程; 对应起来就是刚才说的main目录和renderer目录 main目录放主进程相关的东西 renderer目录放界面相关的东西 如果你开发过vue的程序,你不会对renderer目录下的东西陌生,就是一个纯粹的vue项目应有的东西 main目录下,一个index.js,一个index.dev.js 如果你的程序处于调试状态,那么这两个文件都会起作用(通过npm run dev命令启动的程序); 如果你的程序处于发布状态,那么只有index.js文件起作用(通过npm run build命令编译打包后被安装的程序); 如果你看了package.json文件 会发现如下配置: 1 "main":"./dist/electron/main.js" 这是electron程序启动的入口, 这里的main.js就是index.js和index.dev.js合并打包出来的 注:nwjs入口程序是一个.html的文件;electron的入口程序是一个.js的文件 electron通过js入口程序加载画面 在咱们这个工程下,他加载的事src目录下的index.ejs画面 这其实也是vue程序的宿主页面 根目录下,还有一个build子目录, 如果没有,你执行一下npm run build命令就有了, 你产品开发完,打包出来的东西,就放在这个目录下; 这个目录下,有一个icons的子目录 打包的时候,从这个子目录里取图标, 打包出来的可执行文件的图标,就是从这里得来的; 还有一个非常重要的目录是根目录下的static目录 前面我们说了electron-vue开发环境和生产环境的不同; 在这个目录里放的,就是一些静态的资源 无论是开发环境,还是生产环境, 你只需要通过下面这样的路径访问方式,就能加载到相应的资源 1 src="static/your/path/file.js" 程序的启动与关闭 electron程序的入口是一个js文件 在js文件里打开一个窗口,让这个窗口加载指定的画面 1 2 3 4 5 6 7 8 9 functioncreateWindow () { mainWindow = newBrowserWindow({ height:800, useContentSize:true, width:1200}) mainWindow.loadURL(winURL) mainWindow.on('closed', ()=>{mainWindow =null}) } app.on('ready', createWindow); app在ready的时候,创建了一个窗口,并加载了一个路径 app和窗口都是通过下面的代码得来的: 1 import{ app, BrowserWindow } from 'electron' 路径是通过下面的代码得来的: 1 2 3 constwinURL = process.env.NODE_ENV === 'development'? `http://localhost:9080`: `file://${__dirname}/index.html` electron允许打开子窗口,也允许开多标签页 在苹果端,当所有窗口都关闭后,就要退出程序,代码如下: 1 2 3 4 5 app.on('window-all-closed', ()=>{ if(process.platform !== 'darwin') { app.quit(); } }) 绕不开的博客园登录 其实并不是绕不开,而是绕开的成本太高了,不值得。 就像我们做IT系统,永远没有一个系统是绝对安全的, 如果破坏一个系统的成本足够高,那么我们就认为这个系统是足够安全的; 我们想自己写画面,在自己的画面上显示博客分类、文章列表; 在自己的画面上新建、编辑、保存文章; 这就涉及到跨域的问题 一开始我考虑,自己写模拟登录的代码,登录成功之后自己保存会话信息; 后来发现博客园还有这个东西 要想绕开这个东西,成本一下子高很多 因为这个东西的目的,就是为了防止被绕开的 (其实我有思路,但并未做尝试) 后来想到,就算绕开又如何呢? 难道我去把博客园的服务端接口都分析一遍 真的用自己的代码,访问博客园的接口吗? 我为什么不通过一个隐藏的iframe,来控制博客园的界面 通过它获取我想呈现在自己界面上的数据; 也通过它,提交我自己界面上的用户数据; 这样就只要用博客园前端页面内置的jquery获取文章数据; 然后再用jquery操作提交、草稿按钮就可以了。 在nwjs环境里,我们真的就是用的一个iframe,代码如下: 1 2 var iframeTag = 'nwUserAgent="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3538.400 QQBrowser/9.6.12501.400"'; var articleDiv = ''; 这里涉及到三个特殊的属性 nwdisable: 是为了防止这个iframe加载的页面去调用nwjs的一些功能,比如说格盘,因为毕竟我们加载的页面不是我们自己提供的,要为我们用户的安全着想; nwfaketop: 如果没有这个,在iframe页面里调用window.top,就能访问到我们的页面的window对象,很多厂商都是通过这个来判断自己是不是被别人iframe了,有了这个标签,window.top就访问不到我们 nwUserAgent: 我们通过这个标签来设置iframe加载页面时使用的user-agent,进一步隐藏自己,不被服务提供方发现; 在electron里,不是直接用iframe,而是用了electron内置的一个webview的标签 1 (注意:上面这行代码用到了vue的一些特性) 它也有useragent属性,跟nwjs里的nwUserAgent一样 它默认就是不允许被加载页面访问electron的底层API的, 因为根本就不是iframe,所以window.top也访问不到它的宿主页面; 我的目的是让我的用户使用我开发的画面 我的客户在不需要的时候,不需要看到博客园的任何界面 所以这个webview默认是隐藏的; 在用户第一次打开应用的时候,这个webview会直接加载博客园后台的页面: 1 enterUrl:"https://i.cnblogs.com/posts" 如果你第一次使用这个应用,你本地肯定没有会话信息,所以你访问后台页面,博客园会给你跳转到登录页面; 我们可以在webview的dom-ready事件里监控webview内部的url变化,代码如下: 1 2 3 4 5 6 7 8 9 10 var self = this; var frame = this.$refs.frame; frame.addEventListener("dom-ready",function(e){ if(frame.src.search('https://passport.cnblogs.com/user/signin') == 0) { frame.style.zIndex ="99"; }else{ frame.style.zIndex = "1"; //other code... } }); 当url变成登录页面时,我们就让webview显示出来, 这时我们的应用跟一个普通的浏览器没有任何区别, 我们的客户也是在与博客园的登录页面交互, 当用户登录成功之后,url又会变成https://i.cnblogs.com/posts, 此时,我又让webview隐藏起来,把我自己的界面呈现给用户 这个时候用户已经登录成功了 虽然我自己的界面还是没有博客园的会话信息 但是这个webview已经具备了合法的身份 可以随意访问博客园后台的任意API 接下来,我们的界面就会以这个webview为桥梁,与博客园后台服务进行交互。 小结 想通了这些,我发现我手里多了一把锤子🔨 有很多事情可以做呀 写个自动下单工具、秒杀工具、抢票工具之类的,都是易如反掌; 不会在纠结怎么模拟登陆,就算真要模拟登陆,也不是完全没办法; 因为在这个环境下,目标网站的前端代码,完全暴露在你眼前,随你想怎么控制就怎么控制 具体怎么搞,我们一下篇再说 ,有着急的朋友,可以先看我开源出来的代码 不过,我想要做的就是让这个工具兼容更多的博客 现在博客园已经做差不多了,接下来兼容什么呢?CSDN?知乎?简书?segmentfault?欢迎大家留言; 另外,安装程序的下载地址为:https://gitee.com/xland/cnblogs/releases 大家发现什么问题可以直接提issue,如果大家期待什么新功能,也可以提issue(qq群:51021155) 喜欢的朋友,请帮忙点个赞,给个星https://www.cnblogs.com/liulun/p/10110507.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信