使用electron和vue,以ipc通訊的方式構建客戶端版本的掘金首頁

1. 使用electron-vue新建基於vueelectron環境,更多配置請訪問源項目

npm i -g vue-cli
vue init simulatedgreg/electron-vue my-project
cd my-project
npm i
npm run dev
複製代碼

2. 打通electron主進程與渲染進程的通訊

定義常量做爲channel,也就是事件類型名稱javascript

const CLIENT_NORMAL_MSG = 'CLIENT_NORMAL_MSG'  // 渲染進程發出消息類型
const CRAWLER_NORMAL_MSG = 'CRAWLER_NORMAL_MSG' // 主進程發出消息類型
複製代碼
渲染進程

在渲染進程中,使用vue plugin的形式,具體參見vue官方文檔插件css

ipcRenderereventEmitter的一個實例,在渲染進程中使用,你能夠經過它來像主進程發送同步和異步消息,也能夠經過它來接收來自主進程的消息html

const { ipcRenderer } = require('electron')
  const ipcService = Object.create(null)
  const callbackCache = []

  ipcService.install = Vue => {
    Vue.prototype.$ipcRenderer = {
      send: (msgType, msgData) => {
        ipcRenderer.send(CLIENT_NORMAL_MSG, {
          type: msgType,
          data: msgData,
        })
      },
      on: (type, callback) => {
        callbackCache.push({
          type,
          callback,
        })
      }
    }
    ipcRenderer.on(CRAWLER_NORMAL_MSG, (sender, msg) => {
      callbackCache.forEach(cache => {
        if (cache.type === msg.type) {
          cache.callback && cache.callback(msg.data)
        }
      })
    }) // 監聽主進程的消息
  }

  export default ipcService

複製代碼

vue項目中經過this.$ipcRenderer.on的方式添加主進程發送消息的監聽,經過this.$ipcRenderer.send的方式向主進程發送消息,保證發出消息均爲CLIENT_NORMAL_MSG類型,收到消息均爲CRAWLER_NORMAL_MSG,經過消息中的二級固定參數type來區分具體類型,並能夠經過detach的方式來取消特定的類型的消息的監聽vue

最後在Vue的入口文件,也就是渲染進程的入口文件使用上面定義的插件 Vue.use(ipcService) 渲染進程中的配置完成java


主進程

使用class的方式來定義,須要傳入兩個參數來實例化這個class,須要傳入兩個參數,listener爲監聽消息者,sender爲發送消息者node

ipcMsgHandler中包含了全部的handler,爲其傳入this以便可以在其中向渲染進程發送消息ios

import ipcMsgHandler from './ipcMsgHandler'

  export default class Ipc {
    constructor(listener, sender) {
      this.listener = listener
      this.sender = sender
      this.addListener(CLIENT_NORMAL_MSG, this.handleFn.bind(this))
      this.handlerList = ipcMsgHandler(this)
    }

    handleFn(event, data) {
      try {
        this.handlerList[data.type](event, data.data)
      } catch (error) {
        console.error('handler event error:' + error.message)
      }
    }

    addListener(chanel, cb) {
      this.listener.on(chanel, cb)
    }


    _sendMsg(chanel, msgBody) {
      this.sender.send(chanel, msgBody)
    }

    sendToClient(type, data) {
      this._sendMsg(CRAWLER_NORMAL_MSG, {
        type,
        data,
      })
    }
  }
複製代碼

初始狀態下ipcMsgHandler.js文件git

export default _ipc => ({})
複製代碼

在主進程的入口文件(/src/main/index.js)中對Ipc這個class實例化,其中須要使用的listeneripcMainipcMainipcRenderer不一樣,它只負責對消息的監聽,不復雜發送消息,這裏須要入口文件中的mainWindow下的webContents做爲消息的發送者,因此須要在mainWindow建立成功以後再進行Ipc的實例化github

// ...
function createWindow() {
  mainWindow = new BrowserWindow({
    // ...
  });
  new IpcMgr(ipcMain, mainWindow.webContents)
}
複製代碼

3. 完成具體功能開發

引入element-ui,使用babel配置css按需加載,具體配置方式element-ui官網

分析掘金首頁數據來源

掘金首頁七種分類下數據均來自一個接口,https://timeline-merger-ms.juejin.im/v1/get_entry_by_rank?src=web&limit=20&category=xxx,經過category進行分類的區分web

渲染進程開發

App.js中,在進入頁面和切換分類時向主進程發送消息

// ...
  methods: {
    startRequest() {
      this.$ipcRenderer.send('start-request', this.activeCategory)
    },
    onRequestBack() {
      this.$ipcRenderer.on('request-back', data => {
        // todo...
      })
    },
  }
複製代碼

主進程開發

如今渲染進程中已經定義了兩種消息類型start-requestrequest-backstart-request告訴主進程開始執行任務,完成後request-back告訴渲染進程任務完成,渲染進程收到消息後經過收到的數據來對頁面進行操做。

ipcMsgHandler.js中進行拓展,使用axios對接口內容進行抓取

import axios from 'axios'
  const handlerList = _ipc => ({
    ['start-request'](event, category) {
      const requestBack = data => {
        _ipc.sendToClient('request-back', data)
      }
      axios.get(`https://timeline-merger-ms.juejin.im/v1/get_entry_by_rank?src=web&limit=20&category=${category}`)
        .then(r => {
          if(r.status === 200) {
            requestBack({
              success: true,
              rows: r.data.d.entrylist
            })
          } else {
            requestBack({
              success: false,
              error: `server error code: ${r.status}`
            })
          }
        })
        .catch(e => requestBack({
          success: false,
          error: `server error code: ${e.status} msg: ${e.message}`
        }))
    }
  })
複製代碼

請求完成後,經過requestBack向渲染進程發送消息,渲染頁面,操做樣式調整,頁面看起來大概是這樣。

4. 增長連接跳轉到默認瀏覽器

在該項目中若是直接使用window.open的方式來打開的話,它會新彈出一個electron窗口,全部鏈接跳轉也須要用到ipc的方式

electron中,有一個shell對象,它提供一個openExternal的方法來在默認瀏覽器中打開連接

ipcMsgHandler.js中新增如下內容

const { shell } = require('electron')
  export default _ipc => ({
    ['open-shell'](event, url) {
      shell.openExternal(url)
    },
    // ...
  })
複製代碼

如今就能夠在vue中經過this.$ipcRenderer.send('open-shell', url)的方式來在默認瀏覽器中打開連接了

一個經過打通IPC通訊方式的掘金首頁概覽客戶端就完成了,經過npm run build就能夠對這個應用進行打包了

PS: 其實在electron中是能夠支持跨域訪問的,只須要在建立窗口的時候加上一下配置項就好了,不過結果其實並不重要,重要的是過程了

webPreferences: {
  webSecurity: false,
}
複製代碼

以上代碼均可以在github上找到,歡迎star~~~

相關文章
相關標籤/搜索