Vuex和Electron携带状态进入新窗口

时间:2016-11-17 13:28:20

标签: vue.js electron vuex

我目前正在使用Electron构建一个应用程序,到目前为止这是非常棒的。

我使用Vue.jsVuex来管理我应用的主要状态,主要是用户状态(个人资料和经过身份验证等等)

我想知道是否可以打开一个新窗口,并且具有与主窗口相同的Vuex状态,例如。

如果用户未经过身份验证,我目前会在应用启动时显示一个登录窗口。

function createLoginWindow() {
  loginWindow = new BrowserWindow({ width: 600, height: 300, frame: false, show: false });
  loginWindow.loadURL(`file://${__dirname}/app/index.html`);
  loginWindow.on('closed', () => { loginWindow = null; });
  loginWindow.once('ready-to-show', () => {
    loginWindow.show();
  })
}

用户登录表单,如果成功,则触发此功能:

function showMainWindow() {
  loginWindow.close(); // Also sets to null in `close` event
  mainWindow = new BrowserWindow({width: 1280, height: 1024, show: false});
  mainWindow.loadURL(`file://${__dirname}/app/index.html?loadMainView=true`);
  mainWindow.once('resize', () => {
    mainWindow.show();

  })
}

这一切都有效,唯一的问题是,mainWindowthis.$store&#39 loginWindow的{​​{1}}不共享.close() ; d

有没有办法将Vuex this.$store传递到我的新窗口,所以我不必将所有内容都塞进mainWindow中,不断隐藏它,改变视图,加上我想要的能够拥有依赖于Vuex状态的其他窗口(朋友列表等)。

如果您需要澄清,请希望这不会太混乱。感谢。

3 个答案:

答案 0 :(得分:1)

虽然我可能会看到你如何做到这一点,但我会添加免责声明,因为你使用的是Vue,你不应该这样做。相反,我会使用vue组件来构建这些单独的视图,然后您可以在SPA中实现您的目标。组件也可以是动态的,这可能有助于解决你在mainWindow中隐藏它们的问题,即

<component v-bind:is="currentView"></component>

然后你只需将currentView设置为组件名称,它就可以完全访问你的Vuex商店,同时只安装/显示你想要的视图。

然而,当您调查它时,我相信应该可以将商店的值传递到loginWindowmainWindow,但它不会是纯粹的Vue解决方案。

而是在loginWindows Vue实例中创建一个方法,该方法输出包含您要传递的所有key: value个状态的普通Object。然后将loginWindows变量设置为mainWindow内的全局变量,这将允许它在其存储中更新这些值。即。

# loginWindow Vue model
window.vuexValuesToPass = this.outputVuexStore()
# mainWindow
var valuesToUpdate = window.opener.vuexValuesToPass

然后在mainWindows Vue实例中,您可以设置一个操作来使用您传递的所有值来更新商店

答案 1 :(得分:0)

GuyC关于使应用程序完全单页的建议是有道理的。尝试使用vue-router来管理SPA中路由之间的导航。

我有一个粗略的解决方案来做你想做的事情,它节省了导入类似vue-router的工作量,但是用配置的路由替换页面中的组件总是比加载新页面更顺畅:当打开一个新窗口时,我们有window对象,我们可以将共享状态设置为window的会话存储(或某个全局对象),然后让vuex在新窗口中检索它,如{{1} }。 created() {if(UIDNotInVuex) tryGetItFromSessionStorage();}是某个组件创建的钩子。

答案 2 :(得分:0)

假设您正在使用电子的BrowserWindow进行每次互动,我会使用ipc频道通信。

这是主要过程

import { ipcMain } from 'electron'
let mainState = null

ipcMain.on('vuex-connect', (event) => {
  event.sender.send('vuex-connected', mainState)
})

ipcMain.on('window-closed', (event, state) => {
  mainState = state
})

然后,我们需要为Vuex商店创建一个插件。我们称之为ipc。有一些有用的信息here

import { ipcRenderer } from 'electron'
import * as types from '../../../store/mutation-types'

export default store => {
  ipcRenderer.send('vuex-connect')

  ipcRenderer.on('vuex-connected', (event, state) => {
    store.commit(types.UPDATE_STATE, state)
  })
}

在此之后,使用store.commit更新整个商店状态。

import ipc from './plugins/ipc'
var cloneDeep = require('lodash.clonedeep')

export default new Vuex.Store({
  modules,
  actions,
  plugins: [ipc],
  strict: process.env.NODE_ENV !== 'production',
  mutations: {
    [types.UPDATE_STATE] (state, payload) {
      // here we update current store state with the one
      // set at window open from main renderer process
      this.replaceState(cloneDeep(payload))
    }
  }
})

现在,当窗口关闭被触发或任何其他您喜欢的事件时,仍然会发送vuex状态。将此放在您可以访问商店状态的渲染器过程中。

ipcRenderer.send('window-closed', store.state)

请注意,我没有专门测试上述情况。这是我在一个应用程序中使用的东西,它可以生成新的BrowserWindow实例并在它们之间同步Vuex存储。

此致