本身動手用electron+vue開發博客園文章編輯器客戶端【一】

緣起

以前我用nwjs作過一個博客園文章編輯器的客戶端html

發了好幾個版本,最後一個版本到5.0.0了前端

其實第一個版本已經很好了,不滿足,後來本身又作了兼容markdown的,結果用來用去,發現不是本身想要的vue

也一直沒動手作新的,寫博客的頻率也降下去了。node


最近搞了個APP(還沒上線),打算把心得寫到博客裏,發現沒有趁手的編輯器jquery

因而動手從新搞這個東西git

此次用Vue+electron來搞,算是技術的主流了github

先把搞這個東西的心得寫出來,但願你們不吝賜教。web

界面

截幾個圖給你們看看,chrome

列表界面:vue-cli

文章編輯的界面:

功能

  • 博客登陸(引入博客園的登陸畫面,使用官方提供的登陸機制)

  • 文章列表(能夠檢索到你博客園內全部的隨筆文章,支持分頁,支持文章分類)

  • 修改文章(你博客園內全部的歷史隨筆文章,均可以用此工具編輯修改)

  • 新增文章(從無到有撰寫一篇新的隨筆文章,支持保存爲草稿)

  • 截圖工具截圖後直接黏貼到編輯器中(QQ截圖、微信截圖,直接黏貼到編輯器中)

  • 圖片拖拽到編輯器中自動上傳

  • 插入公式、插入地圖、插入表情、插入表格、插入音樂、插入代碼...包羅萬象;

  • 純客戶端,直接與博客園服務端通訊(沒有任何自建服務,不採集用戶任何信息)

  • 新版本升級提醒功能;

  • 開源,開源地址:https://gitee.com/xland/cnblogs

  • 操做系統兼容蘋果和windows,下載地址:https://gitee.com/xland/cnblogs/releases

搭建環境

這個程序用到了electron和vue

連接這兩個東西的橋樑是electron-vue

建議你們給個star,有這麼個工具真的能省不少力氣(有錢的捧個💰場,沒錢的捧個✨場)

用npm工具初始化環境的命令爲:

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文件

會發現以下配置:

"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開發環境和生產環境的不一樣;

在這個目錄裏放的,就是一些靜態的資源

不管是開發環境,仍是生產環境,

你只須要經過下面這樣的路徑訪問方式,就能加載到相應的資源

src="static/your/path/file.js"

程序的啓動與關閉

electron程序的入口是一個js文件

在js文件裏打開一個窗口,讓這個窗口加載指定的畫面

functioncreateWindow () {
    mainWindow = newBrowserWindow({
        height:800,
        useContentSize:true,
        width:1200})
    mainWindow.loadURL(winURL)
    mainWindow.on('closed', ()=>{mainWindow =null})
}
app.on('ready', createWindow);

app在ready的時候,建立了一個窗口,並加載了一個路徑

app和窗口都是經過下面的代碼得來的:

import{ app, BrowserWindow } from 'electron'

路徑是經過下面的代碼得來的:

constwinURL = process.env.NODE_ENV === 'development'?
    `http://localhost:9080`:
    `file://${__dirname}/index.html`

electron容許打開子窗口,也容許開多標籤頁

在蘋果端,當全部窗口都關閉後,就要退出程序,代碼以下:

app.on('window-all-closed', ()=>{
    if(process.platform !== 'darwin') {
        app.quit();
    }
})

繞不開的博客園登陸

其實並非繞不開,而是繞開的成本過高了,不值得。

就像咱們作IT系統,永遠沒有一個系統是絕對安全的,

若是破壞一個系統的成本足夠高,那麼咱們就認爲這個系統是足夠安全的;


咱們想本身寫畫面,在本身的畫面上顯示博客分類、文章列表;

在本身的畫面上新建、編輯、保存文章;

這就涉及到跨域的問題

一開始我考慮,本身寫模擬登陸的代碼,登陸成功以後本身保存會話信息;

後來發現博客園還有這個東西

要想繞開這個東西,成本一會兒高不少

由於這個東西的目的,就是爲了防止被繞開的

(其實我有思路,但並未作嘗試)


後來想到,就算繞開又如何呢?

難道我去把博客園的服務端接口都分析一遍

真的用本身的代碼,訪問博客園的接口嗎?

我爲何不經過一個隱藏的iframe,來控制博客園的界面

經過它獲取我想呈如今本身界面上的數據;

也經過它,提交我本身界面上的用戶數據;

這樣就只要用博客園前端頁面內置的jquery獲取文章數據;

而後再用jquery操做提交、草稿按鈕就能夠了。


在nwjs環境裏,咱們真的就是用的一個iframe,代碼以下:

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 = '<iframe id="articleFrame" src="[your url]" nwdisable nwfaketop '+bky.iframeTag+'></iframe>';

這裏涉及到三個特殊的屬性

  • nwdisable:

是爲了防止這個iframe加載的頁面去調用nwjs的一些功能,好比說格盤,由於畢竟咱們加載的頁面不是咱們本身提供的,要爲咱們用戶的安全着想;

  • nwfaketop:

若是沒有這個,在iframe頁面裏調用window.top,就能訪問到咱們的頁面的window對象,不少廠商都是經過這個來判斷本身是否是被別人iframe了,有了這個標籤,window.top就訪問不到咱們

  • nwUserAgent:

咱們經過這個標籤來設置iframe加載頁面時使用的user-agent,進一步隱藏本身,不被服務提供方發現;


在electron裏,不是直接用iframe,而是用了electron內置的一個webview的標籤

<webview ref="frame" :preload="preloadJsPath" :src="enterUrl" :useragent="$root.agent"></webview>

(注意:上面這行代碼用到了vue的一些特性)

它也有useragent屬性,跟nwjs裏的nwUserAgent同樣

它默認就是不容許被加載頁面訪問electron的底層API的,

由於根本就不是iframe,因此window.top也訪問不到它的宿主頁面;


個人目的是讓個人用戶使用我開發的畫面

個人客戶在不須要的時候,不須要看到博客園的任何界面

因此這個webview默認是隱藏的;


在用戶第一次打開應用的時候,這個webview會直接加載博客園後臺的頁面:

enterUrl:"https://i.cnblogs.com/posts"

若是你第一次使用這個應用,你本地確定沒有會話信息,因此你訪問後臺頁面,博客園會給你跳轉到登陸頁面;

咱們能夠在webview的dom-ready事件裏監控webview內部的url變化,代碼以下:

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)

喜歡的朋友,請幫忙點個贊,給個星

相關文章
相關標籤/搜索