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

回顧

上一篇文章中,html

我們聊了我開發的這個程序是什麼樣子、爲何要開發這個程序前端

electron的工程結構,他是怎麼啓動和退出的vue

以及咱們怎麼用electron的技術,登陸博客園,拿到會話信息;jquery

這篇文章,咱們主要講怎麼拿博客園的數據,以及怎麼提交數據給博客園;git

上幾張新圖:github

宿主畫面與webview通訊的問題 

在nwjs裏,宿主頁面與作過特殊標記的iframe頁面(nwdisable nwfaketop和nwUserAgent)通訊,並無什麼特別的地方web

就像你在一個普通的頁面裏訪問你本身的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

相關文章
相關標籤/搜索