回顧
在上一篇文章中,
咱們聊了我開發的這個程序是什么樣子、為什么要開發這個程序
electron的工程結構,他是怎么啟動和退出的
以及我們怎么用electron的技術,登錄博客園,拿到會話信息;
這篇文章,我們主要講怎么拿博客園的數據,以及怎么提交數據給博客園;
上幾張新圖:




宿主畫面與webview通信的問題
在nwjs里,宿主頁面與做過特殊標記的iframe頁面(nwdisable nwfaketop和nwUserAgent)通信,並沒有什么特別的地方
就像你在一個普通的頁面里訪問你自己的iframe子頁面一樣
var frame = document.getElementById('[yourFrameId]').contentWindow;
可以通過上面的代碼,輕而易舉的得到iframe頁面的window對象;
注意:被標記了nwfaketop的子頁面里的代碼是訪問不到父頁面的window對象的;
然而在electron里,宿主頁面要想跟webview頁面通信的話,事情就復雜的多了
你要給webview頁面配置preload屬性,
讓webview把你一個你自己寫的JS文件注入到目標頁面里去,如下:
<webview preload="[your js file path]" src="http://[yourTargetUrl]"></webview>
你可以在這個JS文件里訪問目標頁面上任何東西,就像你自己寫了一個JS文件放在目標網站里一樣;
不僅如此,你還可以在這個JS文件里訪問electron提供的底層API;
然而怎么把訪問到的東西呈現在自己的畫面上呢
比如,我們在這個JS文件里拿到了博客分類的數據:
var temp = $("#post_categories a[href^='/posts?categoryid=']");
注:博客園是我們的目標網站,目標網站加載了jquery,我們這個注入的js也可以使用jquery的能力
再通過如下代碼反饋給我們自己的畫面
const {ipcRenderer} = require('electron')
ipcRenderer.sendToHost('messageFromWeb', temp);
ipcRenderer就是electron里的東西了,
看這個API就知道,這是在通過消息的方式通信,
我們需要在自己的畫面里監聽這個消息
var webViewInstance = document.getElementById('[yourWebViewId]');
webViewInstance.addEventListener("ipc-message", event=>{
console.log(event.args[0]);
}
這里event.args[0]就是注入JS里傳過來的temp對象,也就是博客分類的數據了
接下來,就想怎么呈現就怎么呈現。
如果想把自己畫面里的數據傳遞給注入的JS代碼
需要在自己畫面發送消息,代碼如下:
var webViewInstance = document.getElementById('[yourWebViewId]');
webViewInstance.send("messageFromHost","hookSaveArticle",{data:'your article data'});
在注入的JS代碼里,可以通過下面的代碼來獲取宿主頁面發送過來的消息:
const {ipcRenderer} = require('electron')
ipcRenderer.on('messageFromHost', (event, action, obj)=>{
console.log(action); //print hookSaveArticle
console.log(obj); //print {data:'your article data'}
})
以上,
我們現在可以自由的在目標頁面和宿主頁面互相通信,傳遞數據了;
但是!
File類型和Blob類型的數據不能這樣傳遞,這是官網文檔里並沒有說明的,是我自己踩坑踩出來的
那么這樣的數據該怎么發送呢?
我是先在發送方轉成base64,再在接收方轉回來達到目的的
雖然有點脫了褲子放屁,但是聊勝於無呀!
發送方的代碼如下:
window.editorUpload = function(file) {
var reader = newFileReader();
reader.readAsDataURL(file);
reader.onload = function() {
webViewInstance.send("messageFromHost","hookUploadPic", {base64:reader.result,
name:file.name});
};
}
接收方的代碼如下:
functiondataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = newUint8Array(n);
while(n--) { u8arr[n] = bstr.charCodeAt(n); }
return newFile([u8arr], filename, {type: mime});
}
ipcRenderer.on('messageFromHost', (event, action, param)=>{
var file = dataURLtoFile(param.base64, param.name);
})
與編輯器相關的問題
我們用的是NEditor編輯器,前身是百度的UEditor編輯器,不過百度的UEditor已經不再維護了
然而,就算NEditor編輯器,我也修改了里面很多東西
上傳文件,我們上一個章節說過了,不得不修改,
因為我們要把用戶貼過來的圖片發送給鈎子JS,而不是直接upload到自己的服務器上;
我大概在neditor.all.js的26616行,加了一行自己的代碼,大家可以去看我的源碼
以后打算讓這個編輯器方便的兼容base64,這樣就不用事先把圖片傳博客園服務器上去了,不知道這個思路靠譜不靠譜;
另外,因為編輯器相關的前端文件都是靜態資源,我就把他們放到static目錄下去了
這樣只要在主頁直接把這些靜態資源加載過來就可以了
<script src="static/editor/neditor/neditor.config.js"></script> <script src="static/editor/neditor/neditor.all.js"></script> <script src="static/editor/neditor/neditor.service.js"></script> <script src="static/editor/neditor/i18n/zh-cn/zh-cn.js"></script>
其他的一些樣式文件,ueditor自己會自動加載,路徑也不會有什么問題
多標簽頁的問題
在我上一個版本的程序里,一次只能編輯一篇文章

有人反映說,這樣不是很方便,於是這個版本做了多標簽頁的功能;
首先,我用一個數組存儲每個標簽頁的基礎數據
tabs: [{text:"文章列表",
url:"https://i.cnblogs.com/posts",
isHomePage:true,
pageType:'list',
data:null
}],
vue的模板代碼里呈現這個數組的數據:
<div @click="selectTab(index)" v-for="(tab,index) in tabs">
程序剛啟動的時候,就這么一個標簽頁,當用戶點了文章列表的某條文章的時候,執行下面的方法
articleClick(url, text) {
var obj = {url,text,"pageType":"editor",data:null};
this.tabs.push(tab);
this.webViewInstance.loadURL(url);
}
這樣就多了一個標簽頁;
因為我們這個程序,只有兩種類型的畫面,不是文章列表,就是編輯文章(添加文章和編輯文章是同樣的畫面)
所以,雖然是多個標簽頁,也不過是在這兩種畫面間切換
vue的模板代碼如下
<div class="main"> <list v-show="tabs[tabsSelectedIndex].pageType == 'list'"></list> <editor v-show="tabs[tabsSelectedIndex].pageType == 'editor'"></editor> </div>
根據當前tab頁的類型,切換畫面;
每次新tab頁的加入,我們就迫使webViewInstanceload一下tab對應的url,以拿到目標頁的數據;
每次tab頁的切換,我們就從tab數組元素里拿data數據,其實就相當於我們緩存的數據(並沒有存成本地文件或本地數據庫呢);
由於UEditor不是一個VUE組件,所以我們在切換頁面,新加頁面的時候,要通過UEditor的API獲取數據,重置數據,代碼如下:
UE.instants.ueditorInstant0.getContent(); UE.instants.ueditorInstant0.setContent(content);
總結
寫到這里,發現並沒有什么特殊的東西需要在博客里解釋了
還有不明白的地方的讀者,自己去看源碼吧!
下載地址:www.xiangxuema.com
謝謝大家的支持;
接下來我打算為這個程序加入下面這些功能:
-
刪除文章
-
編輯分類
-
支持CSDN博客
-
支持開源中國博客
-
支持簡書
-
支持知乎
-
......
請大家多多關注:https://github.com/xland/xiangxuema
