在新窗口中打开一个 VueJS 组件

use*_*142 9 window.open vue.js vue-component vuejs2

我有一个只有一页的基本 VueJS 应用程序。它不是 SPA,我也不使用 vue-router。

我想实现一个按钮,当单击该按钮时,它会使用来自我的 Vue 组件之一的内容执行 window.open() 函数。

查看文档,window.open()我看到了以下 URL 声明:

URL 接受指向 HTML 页面、图像文件或浏览器支持的任何其他资源的路径或 URL。

是否可以将组件作为参数传递给window.open()

Ale*_*iew 21

我能够使用一篇关于 React 中的门户的文章中的一些见解来创建一个 Vue 组件,该组件能够在新窗口中挂载其子项,同时保持反应性!这很简单:

<window-portal>
  I appear in a new window!
</window-portal>
Run Code Online (Sandbox Code Playgroud)

在这个代码和盒子里试试吧!

该组件的代码如下:

<template>
  <div v-if="open">
    <slot />
  </div>
</template>

<script>
export default {
  name: 'window-portal',
  props: {
    open: {
      type: Boolean,
      default: false,
    }
  },
  data() {
    return {
      windowRef: null,
    }
  },
  watch: {
    open(newOpen) {
      if(newOpen) {
        this.openPortal();
      } else {
        this.closePortal();
      }
    }
  },
  methods: {
    openPortal() {
      this.windowRef = window.open("", "", "width=600,height=400,left=200,top=200");
      this.windowRef.addEventListener('beforeunload', this.closePortal);
      // magic!
      this.windowRef.document.body.appendChild(this.$el);
    },
    closePortal() {
      if(this.windowRef) {
        this.windowRef.close();
        this.windowRef = null;
        this.$emit('close');
      }
    }
  },
  mounted() {
    if(this.open) {
      this.openPortal();
    }
  },
  beforeDestroy() {
    if (this.windowRef) {
      this.closePortal();
    }
  }
}
</script>
Run Code Online (Sandbox Code Playgroud)

关键是线this.windowRef.document.body.appendChild(this.$el);这一行有效地<div>从父窗口中删除了与 Vue 组件(顶层)关联的 DOM 元素,并将其插入到子窗口的主体中。由于这个元素Vue 通常更新的引用相同,只是在不同的地方,一切正常 - Vue 继续更新元素以响应数据绑定更改,尽管它被安装在新窗口中。我真的很惊讶这有多简单!


dr_*_*rto 6

您无法传递 Vue 组件,因为window.open不了解 Vue。然而,您可以做的是创建一个显示您的组件的路由,并将该路由的 URL 传递给window.open,从而为您提供一个包含组件的新窗口。不过,不同窗口中的组件之间的通信可能会变得很棘手。