使用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~~~

相关文章
相关标签/搜索