最小例子:从反应应用中打开电子窗口?

时间:2017-03-11 12:36:56

标签: javascript reactjs electron

假设我正在构建一个带有react / redux& amp;的桌面应用程序。电子。所以我在电子中的index.html文件如下所示:

<!DOCTYPE html>
<html>
 ...
  <body>

    <div id="content"></div>

  <script src="public/js/bundle.js"></script>
  </body>
</html>

我最大的React容器(称为app.js)被加载到'id = content'div中。到目前为止这个工作正常,但现在我想知道如何在用户单击我的react应用程序中的按钮时打开一个新的文件对话框窗口(或任何新窗口)。

我找到了一些例子here&amp; here,但这两个示例仅解释了如何从主电子过程(渲染器或主要)加载文件对话框窗口。

但是,我希望用户使用我的React应用程序然后,一旦他或她点击一个按钮,我的应用程序应该告诉电子产生一个新窗口,当然,这个新窗口应该是某种程度上的一部分我的反应应用程序。

如果有人能在这里提供一个最简单的例子,我会非常感激,关于这些事情如何协同工作。

2 个答案:

答案 0 :(得分:5)

要在新窗口中单击按钮来打开react组件并检测窗口何时关闭 ,因为关闭窗口时组件不会简单地调用componentWillUnmount < / em>您的应用应该看起来像这样

App.js

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      // To keep track of the new window if opened or closed
      isNewWindow: false,
    };
  }

  render() {
    return(
    // onClose will be fired when the new window is closed
    // everything inside NewWindowComponent is considered props.children and will be
    // displayed in a new window
    {(this.state.isNewWindow) &&
    <NewWindowComponent
      onClose={() => this.setState({ isNewWindow: false })>
      <h2>This will display in a new window</h2>
    </NewWindowComponent> }

    <button
      onClick={() => this.setState({ isNewWindow: true })}>
      Open in new window</button>
    )
  }
}

NewWindowComponent.js

export default class NewWindowComponent extends Component {
  // Create a container <div> for the window
  private containerEl = document.createElement('div');

  // This will keep a reference of the window
  private externalWindow = null;

  // When the component mounts, Open a new window
  componentDidMount() {
    // The second argument in window.open is optional and can be set to whichever
    // value you want. You will notice the use of this value when we modify the main
    // electron.js file
    this.externalWindow = window.open('', 'NewWindowComponent ');

    // Append the container div and register the event that will get fired when the
    // window is closed
    if (this.externalWindow)
    {
      this.externalWindow.document.body.appendChild(this.containerEl);
      this.externalWindow.onunload = () => this.props.onClose();
    }
  }

  render() {
    return ReactDOM.createPortal(this.props.children, this.containerEl);
  }
}

electron-main.js ,或者您的主电子文件被命名为

...
function createWindow() {
  mainWindow = new BrowserWindow({
    ...
    // You need to activate `nativeWindowOpen`
    webPreferences: { nativeWindowOpen: true },
  });
  ...
  mainWindow.webContents.on('new-window',
    (event, url, frameName, disposition, options, additionalFeatures) =>
    {
      // This is the name we chose for our window. You can have multiple names for
      // multiple windows and each have their options
      if (frameName === 'NewWindowComponent ') {
        event.preventDefault();
        Object.assign(options, {
          // This will prevent interactions with the mainWindow
          parent: mainWindow,
          width: 300,
          height: 300,
          // You can also set `left` and `top` positions
        });
        event.newGuest = new BrowserWindow(options);
    }
  });
  ...
}
...

答案 1 :(得分:2)

反应16中的“createPortal”api将对您有所帮助。

首先,我们假设我们有一个这样的组件:

<SubWindow>
  <h1>bar</h1>
</SubWindow>

然后在其生命周期方法中打开(或关闭)一个窗口,如下所示:

export class SubWindow extends React.Component {
  nativeWindowObject: null;

  componentWillMount() {
    this.nativeWindowObject = window.open('');
  }
  render() {
    return this.nativeWindowObject ? ReactDOM.createPortal(this.props.children, this.nativeWindowObject.document.body) : null;
  }
}

注意:您必须在主窗口中设置webPreferences:{nativeWindowOpen:true},以确保“window.open”返回本机Window对象。请访问https://electronjs.org/docs/api/window-open了解详情。